2017-02-16 4 views
0

私は、移動コンストラクタをサポートしていないGNU C++コンパイラを使用しています。これは98標準のみをサポートしています。RAII、Berkeley Sockets、およびSTL Container

私は、バークレースタイルのソケットをRAIIに従う簡単な方法でラップするC++クラスを作成したいと考えています。ここでは非常に単純なクラスです:

class SimpleSocket 
{ 
    int m_sockfd; 
public: 
    SimpleSocket() 
    { 
    m_sockfd = socket(AF_INET, ...); 
    } 
    SimpleSocket(const SimpleSocket& other) 
    { 
    m_sockfd = other.m_sockfd; 
    } 
    ~SimpleSocket() 
    { 
    closeSocket(); 
    } 
    void closeSocket() 
    { 
    if(m_sockfd != -1) 
    { 
     close(m_sockfd); 
     m_sockfd = -1; 
    } 
    } 
}; 

のは、私はそうのようなSTLのC++ベクトルにこれらの全体の束を作成したいとしましょう。

vector<SimpleSocket> vec_of_sockets; 
for(int i = 0 ; i < 10 ; ++i) 
{ 
    SimpleSocket new_sock; 
    vec_of_sockets.push_back(new_sock); 
} 

私が見つけたのは、ベクターがコピーコンストラクタを使用してオブジェクトを移動し、古いソケットを破棄していたことでした。これは私のファイル記述子を閉じるcloseSocket()を呼び出すという不幸な副作用があります。

オブジェクトのデストラクタが呼び出されたときにRAIIをフォローしてファイルディスクリプタを閉じたいが、STL C++コンテナ内で使用できない場所に置いておきたい。私は私のコンパイラを更新し、問題を解決する移動コンストラクタを実装することができますが、私は現代的なものを使用することを信じていない会社のために働くことを知っています。 (私は実際にそれでイライラだが、私はそれについてできることは何もありません。)

+0

コピーコンストラクタを変更し、 'const'を削除してから、コピーした後に' other.m_sockfd'を-1に設定してみてください。おそらく、 'operator ='について考えることもあります。 –

+0

@RichardCritten const参照なしでコピーコンストラクタを使用することはできません。あなたの提案は無意味です –

+0

@DavidHaimはいできます:_ "クラスTのコピーコンストラクタは、最初のパラメータが__T&__、const T&、volatile T&、またはconst volatile T&" _(my bold) ://en.cppreference.com/w/cpp/language/copy_constructor一時的なオブジェクトはコピーされません。そのため、私は自分の投稿で「試してください」と言っています。 –

答えて

1

あなたがSmart Pointers Boost libraryを使用することができれば、同様のshared_ptrの内側に自分のクラスを格納します。

std::vector<boost::shared_ptr<SimpleSocket>> 
2

LinuxとWindowsの両方を実装しますカーネル/ winsock2レベルの参照カウント。あなたはあなたのユーザーモードプログラムで参照カウントポインタを使用することができたかもしれませんが、それはあなたが考えるよりも多くのメモリを無駄にするでしょう。 OSがすでに舞台裏で行っている参照カウントを高めることができます。ここではLinux用の実装例です:

SimpleSocket(const SimpleSocket& other) 
    { 
    m_sockfd = dup(other.m_sockfd); 
    } 

オペレーティングシステムは、指定されたソケットの参照カウントをインクリメントしますし、使用可能な新しい記述子を返します。ソケットをこのように「コピー」すると、ディスクリプタが異なっていても、両方のソケットが同じ基本ソケットを参照することに注意してください。

+1

Windowsでは[WSADuplicateSocket](https://msdn.microsoft.com/en-us/library/windows/desktop/ms741565(v = vs.85).aspx)を使用する必要があります。クラスのオーバーロードされた代入演算子も実装します。 – selbie

+0

なぜか分からないけど、私がやっていたことでこれがうまくいかないと思った。私はそれは問題が各ファイル記述子が同じものを参照したので、私は1つを閉じる場合は、他のものを閉じるだろうと思った。 –

+0

@selbieオーバーロードされた代入演算子については、割り当てを禁止する(例外をスローする)か、コピーコンストラクタのようにソケットをdup()しますか? –

関連する問題