2016-12-01 5 views
13

は、私はC++で次のコードがあるとします。std :: make_uniqueを使用すると、一意でないポインタが使用されますか?

#include <memory> 
#include <iostream> 

struct Some { 
     Some(int _a) : a(_a) {} 
     int a; 
}; 

int main() { 
     Some some(5); 

     std::unique_ptr<Some> p1 = std::make_unique<Some>(some); 
     std::unique_ptr<Some> p2 = std::make_unique<Some>(some); 

     std::cout << p1->a << " " << p2->a << std::endl; 
     return 0; 
} 

私は理解しているように、ユニークなポインタはリソースが共有されていないことを保証するために使用されています。しかし、この場合、p1p2の両方が同じインスタンスsomeを指しています。

状況を公開してください。

+1

ポインターの「a」フィールドではなく、ポインターの値を印刷した場合、状況を診断するのは簡単でした。または、あなたは "大きな"コピーコンストラクタを作っていました。また、最も基本的なエラーは 'make_unique'が与えられたオブジェクト(ここではローカル変数' some')へのポインタを生成すると考えることでしょう。これはそれが何をするのかではない。 –

+2

私は完全に貧しいポストは非常に多くのupvotesを得たことに驚いています。 SOの何が問題なの? – Walter

答えて

26

を使用して、同じオブジェクトから構築しますそれ。あなたは、エラーを参照してコピーコンストラクタを削除することによって、それを説明することができます。

#include <memory> 
#include <iostream> 

struct Some { 
     Some(int _a) : a(_a) {} 
     Some(Some const&) = delete; 
     int a; 
}; 

int main() { 
     Some some(5); 

     std::unique_ptr<Some> p1 = std::make_unique<Some>(some); //error here 
     std::unique_ptr<Some> p2 = std::make_unique<Some>(some); 

     std::cout << p1->a << " " << p2->a << std::endl; 
     return 0; 
} 
+4

「unique_ptr」には一意の所有権を強制する手段はないが、それを指摘する価値はある。不注意なプログラマーは、2つの異なる 'unique_ptr'の間で同じオブジェクトの所有権を簡単に共有できます。これは、実行時に未定義の動作を引き起こす可能性が最も高くなります。 – ComicSansMS

+0

@ComicSansMS、あなたは100%正しいです。しかし、私はどのようにそれを行うことができるかを示す例を追加することについて相反しています... – StoryTeller

+6

私は同意する傾向があります。自分の足を吹き飛ばす方法を人々に示す必要はありません。 – ComicSansMS

16

std::make_uniqueは、引数を指定してコンストラクタを呼び出してオブジェクトを作成します。

パラメータとしてSome&を渡しました。コピーコンストラクタが呼び出され、新しいオブジェクトが構築されました。

そこで彼らは、異なるコピーの各ポイント、P1、P2は2つの全く異なるポインタがありますが、彼らは同じリソースを指していないコピーコンストラクタ

1

二つのポインタが同じオブジェクトのインスタンスを指すかどうかをテストするには、あなたの代わりに、オブジェクトのメンバ変数の彼らが指す場所を、比較する必要があります。

std::cout << &(*p1) << " " << &(*p2) << std::endl; 

これは実際にはではなく、が同じインスタンスを指していることを示します。

補足:C++ 11は、レミールボーにより指摘したように、&オペレータがオーバーロードされた場合でも、オブジェクトの実際のアドレスを取得する、この目的のため std::addressof関数を使用することが推奨される:

std::cout << std::addressof(*p1) << " " << std::addressof(*p2) << std::endl; 
+2

クラスがカスタムの 'operator&'を実装している場合、このコードは失敗します。これは、 'std :: addressof()'が解決するために導入されたものです: 'std :: addressof(* p1)<< std :: addressof(* p2)<< std :: cout endl; ' –

+0

あなたは正しいです、ありがとうございます。与えられた例では、必ずしも必要ではありませんが、とにかくそれを使うのは確かです。私は答えに加えました。 – Meyer

9

both p1 and p2 point to the same instance some

No, they don't.

#include <memory> 
#include <iostream> 

struct Some { 
     Some(int _a) : a(_a) {} 
     int a; 
}; 

int main() { 
     Some some(5); 

     std::unique_ptr<Some> p1 = std::make_unique<Some>(some); 
     std::unique_ptr<Some> p2 = std::make_unique<Some>(some); 

     std::cout << p1->a << " " << p2->a << std::endl; 
     p1->a = 42; 
     std::cout << p1->a << " " << p2->a << std::endl; 
     return 0; 
} 

出力:

5 5 
42 5 
関連する問題