2017-03-04 46 views
1

私は本当にC++ 98からC++ 11以上に移行しようとしています。私は新しいもののほとんどの上に私の頭を包みましたが、私はまだunique_ptrの正しい使い方についてはわかりません。クラスメンバーのunique_ptrの正しい使い方

クラスAがunique_ptrメンバを持っている(私は前に生のポインタを使用していました!)以下の例を考えてみましょう。このメンバ変数は、ユーザが必要とするときに、他の場所の関数(クラスの一部ではない)を呼び出すことによって割り当てる必要があります。これは正しい使用法ですか?そうでない場合、最良の選択肢は何ですか?

class A { 
private: 
    unique_ptr<MyType> mt; 
public: 
    void initStuff() { 
     mt.reset(std::move(StaticFuncSomewhereElese::generateMyType())); 
    } 
}; 

MyType* StaticFuncSomewhereElese::generateMyType() { 
    MyType* temp = new MyType(...); 
    //do stuff to temp (read file or something...) 
    return temp; 
} 
+2

そこに 'std :: move'は必要ありません。生ポインタは移動できません。 – emlai

+0

@tuple_catしかし、これは完璧にコンパイルされ実行されます。 –

+0

@SaeidYazdaniあなたはそれを必要としません。代わりに 'std :: make_unique()'を使います。 –

答えて

3

あなたのコードは正常に動作します(冗長ものの* moveを省略することができる)が、可能な限り早期にunique_ptrを構築する方が良いでしょう:

classss A { 
private: 
    std::unique_ptr<MyType> mt; 
public: 
    void initStuff() { 
     mt = StaticFuncSomewhereElese::generateMyType(); 
    } 
}; 

std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType() { 
    auto temp = std::make_unique<MyType>(…); 
    // `make_unique` is C++14 (although trivially implementable in C++11). 
    // Here's an alternative without `make_unique`: 
    // std::unique_ptr<MyType> temp(new MyType(…)); 

    //do stuff to temp (read file or something...) 
    return temp; 
} 

それが復帰することが明らかである。この方法generateMyTypeの値は呼び出し元によって削除されなければならず、メモリリークの可能性は低くなります(たとえば、generateMyTypeが早期に返される場合)。生のポインタが移動することはできません

  1. :ので

    * moveは冗長です。

  2. generateMyType()の結果は、すでにいずれの場合も既に値です。
+2

質問にはC++ 11というタグが付いているので、 'std :: make_unique'はC++ 14まで導入されていないことに言及する価値があります。 – user2079303

3

これは正しい使い方ですか?

さらに、std::moveは冗長ですが、これは正しいです。 a)裸ポインタがlvalueまたはrvaluesであるかどうかにかかわらずコピーされます。b)関数が参照を返さないため、戻り値はすでにrvalueであるため、変換する必要はありません。

しかし改善の余地があります。特に、私は、ファクトリ関数から独自のポインタを返すことをお勧めします:

std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType() 

これは、初期化が例外をスローした場合漏れるtempを防ぎ、そしてそれははるかに困難工場のユーザーが誤って漏れるようになり返さポインタ。

関連する問題