2016-10-10 16 views
4

私は次のようにstd::shared_ptrnewとオペレータを定義しようとしているとのstd :: shared_ptrを定義するとき:エラーは、new演算子

main.cpp: In function 'int main()':

main.cpp:8:30: error: conversion from 'A*' to non-scalar type 'std::shared_ptr' requested std::shared_ptr ptr = new A();

#include <memory> 

struct A { 
}; 

int main() { 

    std::shared_ptr<A> ptr = new A(); 

    return 0; 
} 

を、私は、次のコンパイル時のエラーを得ました

とにかく、次は間違いなく動作します:

 std::shared_ptr<A> ptr{new A()}; 

があなたの誰もがkのんなぜこれが起こるのでしょうか?

答えて

6

t1; dr:これは、関連するコンストラクタがexplicitであるためです。

=で初期化すると、コピー初期化が呼び出されます。 C++では、rawポインタからのshared_ptrのコピー初期化は許可されていません。これは、任意の未加工ポインタから実際には管理していないshared_ptrへの偶発的な暗黙的な変換で終了するのが簡単すぎるためです。

このようにして、生ポインタをshared_ptrに "捕まえる"ための唯一の方法は、非常に意図的で非常に明示的です(2番目の例で正しく行ったとおりです)。さて、このイニシャライザでのみ、すでに他の場所で管理しているポインタを使用しないように覚えておく必要があります。

特定の行について実際に危険なことはありますかstd::shared_ptr<A> ptr = new A()?いいえ。しかし、あなたが目にしていることは、さまざまなC++ルールが一緒に協働していることの結果です。

3

あなたはこのような2ライナーとしてもあなたの声明を想像することができます。

A* a = new A(); 
std::shared_ptr<A> ptr = a; 

この場合、これは、コピーの初期化が生ポインタに許可されていないので、それは潜在的な落とし穴をもたらすことができる、より複雑なコードに正しいかもしれないが。

は、ここでは、トラブルの原因と同じオブジェクトを保持する2つの共有のポインタを持っているでしょう

A* a = new A(); 
//..... 
std::shared_ptr<A> ptr = a; 
//..... 
std::shared_ptr<A> ptr2 = a; //second ptr holding a... UB 

を想像してみてください。

これらの「暗黙の」エラーを回避するために、C++ではこの種の初期化を許可していません。

コンストラクタでも同じことができますが、ポインタを誤って割り当てると「冗長」で難しくなります。

std::shared_ptr<A> ptr{ new A() }; 

これは、新しいオブジェクトの作成によく似ており、誤って割り当てが誤っていない可能性があります。

または、現代で共有ポインタを作成する方法は

auto ptr = std::make_shared<A>(); 
+3

好ましいのは、いや、それは代入ではありません。 –

+0

@ LightnessRacesinOrbitええ、あなたは正しいです。私はその部分を改めた。 – Hayt

関連する問題