0

以下の4つの方法では、私たちがすべきことだけがより良いです. ここで動的割り当てを行い、不適切な関数の戻りを回避します。しかし、どこで f を削除するのでしょうか? better() を呼び出す関数で削除しますか? しかし、その場合、もはや f はありません。

Foo *bad() {
  Foo f;
  return &f;
}

Foo &alsoBad() {
  Foo f;
  return f;
}

Foo mediocre() {
  Foo f;
  return f;
}

Foo * better() {
  Foo *f = new Foo;
  return f;
}
4

1 に答える 1

5

しかし、その場合、もはや f はありません。

ポインターはスコープ外になりますが、それは本当ですが、指し示しfたのと同じオブジェクトへのポインターをまだ返しています。f

したがって、そのオブジェクトへのハンドルがまだありdelete、返されたポインターで呼び出すことができます。実際、でオブジェクトを作成した後はdelete いつでも呼び出すことができますnew

気をつけなければならないことは、次のことです。

  • delete実際に、割り当てられた各オブジェクトに対してある時点で呼び出しますnew(そうしないと、メモリ リークが発生します)。
  • delete同じオブジェクトに対して複数回呼び出さないでください。そうしないと、未定義の動作が発生します。
  • 破棄されたオブジェクトを指すポインター (つまり、「ダングリング ポインター」) を逆参照しないでください。そうしないと、未定義の動作が発生します。

new一般に、最新の C++ ではおよびを介した手動のメモリ管理deleteは推奨されておらず、代わりにスマート ポインターを使用して所有権ポリシーを実現する必要があります。また...

以下の4つの方法では、私たちがすべきことだけがより良いです

正確ではありません。実際、絶対にすべきではないと思いますが、所有する生のポインターではなく、スマート ポインターを作成して返すように modified のバージョンを実行することはできますbetter()better()

ただし、機能mediocre()は実際にはかなり優れており、それには次の 2 つの理由があります。

  1. まず第一に、コンパイラがコピー コンストラクターの呼び出しを省略して(名前付き) 戻り値の最適化を実行する可能性が非常に高いため、実行時のオーバーヘッドが発生しません。
  2. 第 2 に、C++11 の移動セマンティクスのおかげで、省略が実行されない場合でも、ほとんどの場合、値による戻りを効率的にするFoo移動コンストラクターを装備できるためです。

さらに、Zoidbergがコメントで正しく言及しているように、ポインターが本当に必要ない場合は、ポインターをまったく使用しないでください。一意の所有権は、多くの場合、自動ストレージ期間 (別名「スタック上」) を持つオブジェクトを作成することで実現でき、ムーブ セマンティクスはこのプラクティスを効率的にします。ポインターは、参照セマンティクスが必要な場合にのみ作成する必要があります。

于 2013-03-30T00:47:35.483 に答える