例を通して私の質問を提起させてください。
#include <memory>
std::unique_ptr<int> get_it() {
auto p = new int;
return p;
}
int main() {
auto up ( get_it() );
return 0;
}
これはコンパイルに失敗し、次のエラーが発生します。
a.cpp:5:9: error: could not convert ‘p’ from ‘int*’ to ‘std::unique_ptr<int>’
return p;
^
生のポインタから一意のポインタへの自動変換がここにないのはなぜですか?そして、私は代わりに何をすべきですか?
動機:所有権を明確にするためにスマートポインターを使用することは良い習慣であると思われることを理解しています。この場合はint*
として、どこかから(私が所有している)ポインターを取得しています。私は(私が思うに)それをunique_ptr
に入れたいと思っています。
コメントしたり、独自の回答を追加したりすることを検討している場合は、 提案N4029でこれを可能にするためのハーバートサターの議論 に対処してください。
答えは2つあります。 OPの自己回答を含む他のすべての回答は、その半分しか扱っていませんでした。
次の理由により、ポインタを自動的に変換できません。
unique_ptr
の- コンストラクタ はexplicit
と宣言されているため、コンパイラは明示的なコンテキストでのみ考慮します。これは、偶発的な危険な変換を防ぐために行われます。この場合、unique_ptr
は、プログラマーの知らないうちにポインターを乗っ取って削除する可能性があります。一般に、unique_ptr
だけでなく、偶発的な変換を防ぐために、すべての単一引数コンストラクターをexplicit
として宣言することをお勧めします。return
を明示するための提案の2つのバージョン( N4029 、 N4074 )、およびそうしないと主張する2つの「応答」: N4094 HowardHinnantおよびVilleVoutilainenおよび N4131 =FilipRoséenによる。いくつかの議論と世論調査の後、問題はNADとしてクローズされました-欠陥ではありません。現在、いくつかの回避策があります。
return std::unique_ptr<int>{p};
または
return std::unique_ptr<int>(p);
C++ 14では、関数の戻り値の型の自動推定も使用できます。
auto get_it() {
auto p = new int;
return std::unique_ptr<int>(p);
}
更新:2番目のポイントの委員会の問題へのリンクを追加しました。
ネイキッドポインタからのunique_ptr
の暗黙的な構築は、エラーが発生しやすいためです。
明示的に作成するだけです。
std::unique_ptr<int> get_it() {
auto p = new int;
return std::unique_ptr<int>(p);
}
なぜならstd::unique_ptr
がポインターの所有権を取得し、生のポインターdelete
dを誤って取得したくないことは間違いありません。
それが可能であれば、次のようにします。
void give_me_pointer(std::unique_ptr<int>) { /* whatever */ }
int main() {
int *my_int = new int;
give_me_pointer(my_int);
// my_int is dangling pointer
}
変換またはキャストには、適切なキャスト演算子(ソースタイプ)またはコンストラクター(ターゲットタイプ)が必要なためです。この場合、それは 必須 _unique_ptr
_の次のコンストラクターです。
_explicit unique_ptr( pointer p );
_
明示的なキーワード があります。 get_it()
は暗黙の変換を試みますが、これはexplicit
が防ぎます。代わりに、 @ Stas および@VincentSavardで提案されているように、_unique_ptr
_を明示的に作成する必要があります。
_std::unique_ptr<int> get_it() {
auto p = new int;
return std::unique_ptr<int>(p);
}
_
または、_unique_ptr
_を1回だけ言いたい場合...
_auto get_it() {
auto p = new int;
return std::unique_ptr<int>(p);
}
_
危険だから。
C++ 14のstd::make_unique()
を使用します。
std::unique_ptr<int> get_it()
{
auto p = std::make_unique<int>();
return p;
}