特定のコンテキストでのキーワードnew
と_&
_の違いについていくつか質問があります。
これが私のコードだとしましょう:
_struct Base {};
struct Foo : Base {};
struct Storage
{
void save(Base * object) {}
Base * content;
};
int main()
{
Storage s1, s2;
s1.save(new Foo());
s2.save(&Foo());
}
_
Mainの実行後、_s1
_はタイプFoo
のオブジェクトへのポインタを保持します。ただし、_s2
_は、タイプBase
のオブジェクトへのポインタを保持します。 _s2.content
_は、saveメソッドの実行が完了するまで、タイプFoo
のオブジェクトのみを指します。
私が間違っている場合は私を訂正してください:
私が理解している限り、new Foo()
はタイプFoo
の新しいオブジェクトへのポインタを作成します。一方、&Foo()
は、最初にタイプFoo
の新しいオブジェクトを作成し、次にそれをポイントします。
では、new Foo()
と&Foo()
の違いは正確には何ですか?明らかに、どちらもタイプFoo
の既存のオブジェクトへのポインタを提供します。
new Foo()
で作成されたオブジェクトが、saveメソッドの実行後も保持されるのに、&Foo()
で作成されたオブジェクトが保持されないのはなぜですか?
&Foo()
が一時オブジェクトを作成し、保存の実行後に存在しなくなる可能性がありますか?はいの場合、&Foo()
を介して作成されたオブジェクトの寿命を延ばして、_s2
_が破壊されるまで(少なくとも)ライブにする方法はありますか?
編集1:迅速な回答をありがとうございました!私は単にVisualStudioを使用しているので、おそらく&Foo()
コンパイルはMicrosoft固有のものです...
では、「
new Foo()
」と「&Foo()
」の違いは正確には何ですか?明らかに、どちらもFoo型の既存のオブジェクトへのポインタを提供します。「
new Foo()
」で作成されたオブジェクトがsaveメソッドの実行後も保持されるのに、「&Foo()
」で作成されたオブジェクトが保持されないのはなぜですか?
new Foo()
_new Foo();
_
これにより、動的に割り当てられたFoo
オブジェクトが作成され、そのオブジェクトを指すポインタが返されます。動的に割り当てられたオブジェクトは、プログラマーによって明示的に削除されるまで存続します。
_Foo* foo = new Foo();
delete foo; // delete the object.
_
&Foo()
_Foo();
_
これにより、automatic-storageを使用してFoo
オブジェクトが作成されます。これは、オブジェクトが削除されたときの存続期間が、オブジェクトが存在するスコープによって決定されることを意味します。
_{
Foo foo{}; // foo lives in automatic storage.
} // end of scope, foo dies
_
あなたの場合、新しいFoo
オブジェクトを作成し、この匿名オブジェクトのアドレスを_Storage::save
_に渡します。このオブジェクトは、完全な式の最後に破棄されます。これは基本的に、s2.save()
が戻った後、オブジェクトが破棄され、_s2
_でオブジェクトを指すポインターがぶら下がり、逆参照が未定義の動作になることを意味します。
はいの場合、「&Foo()」を介して作成されたオブジェクトの寿命を延ばして、(少なくとも)s2が破壊されるまで存続させるにはどうすればよいですか?
できません。ここでは、_std::unique_ptr
_などのスマートポインタが必要になる可能性があります。
一時アドレスの取得は非標準であるため、このコードはそもそも非準拠であることに注意してください。コンパイラはおそらくそれを許可するために拡張機能を使用しています。 MSVCはこれを可能にすることで知られています。
式Foo()
は、新しいtemporaryオブジェクトを作成し、その一時オブジェクトでaddress-of演算子_&
_を使用するとそのような一時オブジェクトのアドレスを取得することは許可されていないため、コンパイラエラーが発生します(Foo()
is rvalue およびaddress-of演算子はそれらに使用できません)。
_new Foo
_を使用して、non一時オブジェクトを作成すると、そのオブジェクトへのポインターが生成されます。このオブジェクトの有効期間は、明示的にdelete
するまでです。そして、それをdelete
しないと、メモリリークが発生します。