Copy constructorと代入演算子
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
[[C++による単純なserver program]]
前節の[[C++による単純なserver program]]は''典型的な誤り例...
ここではこの問題を考察しよう。
どこが誤りであるかというと、mysocket class で
copy constructor と代入演算子が定義
されていない、すなわち default のそれらが使われている点で...
default では各メンバーデータはそのまま代入される。つまり
socket descriptor は int なので、int の代入が起こる。
しかし socket descriptor は socket object を int で表現し...
だけであって数学上の int ではない。四則演算ができるわけで...
代入もしかり。単純に同じ値にすればよいというものではない。
前節の例では accept() でこの問題が起こっている。accept() は
受け入れた新しい mysocket object を返す。
accept関数の中では、mysocket object である tmpsock を
用意し、このデータメンバーを設定して tmpsock を戻り値にして
いる。すなわち tmpsock を呼び出し側 stack へコピーして
関数は終了し、そこから呼び出し側に用意された空の mysocket...
代入される。
では tmpsock はどうなるだろう?関数から抜ける時点で scope...
抜けるので destructor が呼ばれる。destructor は socket de...
close する。今仮に accept した socket descriptor が 5 だ...
5 が closeされる。にもかかわらず 5 は呼び出し側の t の so...
値でもある。つまり t という object は以後 close された 5 ...
操作を行うことになる。これが動作しない理由である。
では、この問題の解決はどうすればよいか?
システムにはこのような目的のために descriptor を複写する...
用意されている。これを使わなければならない。
具体的には dup関数(Windows の場合は DuplicateHandle関数...
使う。
dup関数は、同一実体に対し、異なる descriptor 値を割り当てて
くれる。dup関数を使えばシステムは同一実体に対し、
複数の descriptor を与えたことを認識してくれるので、
一方を close しても実体そのものは解放しない。
割り当てたすべての descriptor が close された時点で初めて...
解放する。従って、例えば descriptor 5 に対し、dup により ...
とすると、5 を close しても 7 は使える。
というわけで、copy constructor と代入演算子を宣言する。
#ifndef MYSOCKET_H_INCLUDED
#define MYSOCKET_H_INCLUDED
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
class mysocket
{
public:
mysocket();
mysocket(const mysocket& from);
mysocket(int domain, int type, int protocol=0);
virtual ~mysocket();
virtual mysocket& operator=(const mysocket& from);
virtual int close();
virtual int connect(const struct sockaddr* addr, sockl...
virtual int bind(const struct sockaddr* addr, socklen_...
virtual int listen(int backlog);
virtual mysocket accept(struct sockaddr* addr, socklen...
virtual int send(const void* msg, size_t len, int flag...
virtual int recv(void* msg, size_t len, int flags=0);
protected:
int m_sd;
};
#endif
つけ加わった copy constructor と代入演算子は dup を使って
mysocket::mysocket(const mysocket& from)
{
m_sd = -1;
if(from.m_sd != -1)
m_sd = ::dup(from.m_sd);
}
mysocket& mysocket::operator=(const mysocket& from)
{
if(&from == this)
return *this;
close();
if(from.m_sd != -1)
m_sd = ::dup(from.m_sd);
return *this;
}
と書ける。
終了行:
[[C++による単純なserver program]]
前節の[[C++による単純なserver program]]は''典型的な誤り例...
ここではこの問題を考察しよう。
どこが誤りであるかというと、mysocket class で
copy constructor と代入演算子が定義
されていない、すなわち default のそれらが使われている点で...
default では各メンバーデータはそのまま代入される。つまり
socket descriptor は int なので、int の代入が起こる。
しかし socket descriptor は socket object を int で表現し...
だけであって数学上の int ではない。四則演算ができるわけで...
代入もしかり。単純に同じ値にすればよいというものではない。
前節の例では accept() でこの問題が起こっている。accept() は
受け入れた新しい mysocket object を返す。
accept関数の中では、mysocket object である tmpsock を
用意し、このデータメンバーを設定して tmpsock を戻り値にして
いる。すなわち tmpsock を呼び出し側 stack へコピーして
関数は終了し、そこから呼び出し側に用意された空の mysocket...
代入される。
では tmpsock はどうなるだろう?関数から抜ける時点で scope...
抜けるので destructor が呼ばれる。destructor は socket de...
close する。今仮に accept した socket descriptor が 5 だ...
5 が closeされる。にもかかわらず 5 は呼び出し側の t の so...
値でもある。つまり t という object は以後 close された 5 ...
操作を行うことになる。これが動作しない理由である。
では、この問題の解決はどうすればよいか?
システムにはこのような目的のために descriptor を複写する...
用意されている。これを使わなければならない。
具体的には dup関数(Windows の場合は DuplicateHandle関数...
使う。
dup関数は、同一実体に対し、異なる descriptor 値を割り当てて
くれる。dup関数を使えばシステムは同一実体に対し、
複数の descriptor を与えたことを認識してくれるので、
一方を close しても実体そのものは解放しない。
割り当てたすべての descriptor が close された時点で初めて...
解放する。従って、例えば descriptor 5 に対し、dup により ...
とすると、5 を close しても 7 は使える。
というわけで、copy constructor と代入演算子を宣言する。
#ifndef MYSOCKET_H_INCLUDED
#define MYSOCKET_H_INCLUDED
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
class mysocket
{
public:
mysocket();
mysocket(const mysocket& from);
mysocket(int domain, int type, int protocol=0);
virtual ~mysocket();
virtual mysocket& operator=(const mysocket& from);
virtual int close();
virtual int connect(const struct sockaddr* addr, sockl...
virtual int bind(const struct sockaddr* addr, socklen_...
virtual int listen(int backlog);
virtual mysocket accept(struct sockaddr* addr, socklen...
virtual int send(const void* msg, size_t len, int flag...
virtual int recv(void* msg, size_t len, int flags=0);
protected:
int m_sd;
};
#endif
つけ加わった copy constructor と代入演算子は dup を使って
mysocket::mysocket(const mysocket& from)
{
m_sd = -1;
if(from.m_sd != -1)
m_sd = ::dup(from.m_sd);
}
mysocket& mysocket::operator=(const mysocket& from)
{
if(&from == this)
return *this;
close();
if(from.m_sd != -1)
m_sd = ::dup(from.m_sd);
return *this;
}
と書ける。
ページ名: