1

次の簡単なコードを考えてみましょう。

    struct test
    {
      test(int n):numelements(n){ arr = new int[numelements] }

      int numelements;
      int* arr;

      ~test()
       {
          delete[]  arr;
       }
    }

   void foo_ref(test& x,n)
   {
       // set first n elements of the array x.arr to random numbers
   }

  void foo_ptr(test* x,n)
   {
       // set first n elements of the array x->arr to random numbers
   }

    int main(void)
    {
     test mystruct(1000000);
     foo_ref(mystruct,20);
     // foo_ptr(&mystruct,20); 


     return 0;
   }

上記のコードでは、それが参照するオブジェクトに対してまったく同じ操作を実行しますfoo_ref。。ただし、foo_refはオブジェクトを参照で渡し、foo_ptrはポインターで渡します。foo_ptrmystruct

どちらの場合も、オブジェクトのデストラクタはどこで呼び出されますか?この質問に対する標準的な答えは常に「オブジェクトのスコープが終了するとき」であることを私は知っています

ただし、参照渡しの場合を考えてみてください。foo_ref mystructの本体内には、その関数のスコープがあります。では、関数の最後でオブジェクトのデストラクタが呼び出されfoo_refませんか?

たぶん私の混乱は何かの範囲の理解に関係しています。私の推論のどこが間違っているのか教えてください。

4

3 に答える 3

3

この辺りには参照がないconstので、答えは「参照とポインタの間でオブジェクトの有効期間に違いはありません」です。

const一時式にバインドされた参照には、一時オブジェクトの存続期間を延長する特別なルールがありますが、それはコードには適用されません。

あなたの混乱は、おそらく非常に人気のあるFAQで行われたステートメントに起因します。それは、「参照は参照されるオブジェクトです」という線に沿ったものです。ご覧のとおり、これは正しくありません。参照は参照するオブジェクトとは別のものであり、それぞれに独自の有効期間があります(これが正しく行われることは非常にまれですが、参照の有効期間がオブジェクトの有効期間より長くなることは合法です)。

于 2012-09-07T23:17:53.010 に答える
1

foo_refパラメータがあり、関数のスコープを持つのはパラメータです。それがポインタであるか参照であるかは、mystructの削除には影響しません。

構造体を値で渡す場合、関数の最後にコピーが破棄されます。コピー内の同じarrを参照するような愚かなことをすると、元の構造体がまだそれを使用しているときに誤ってarrを削除する可能性があります。その場合、手動で削除するのではなく、共有ポインタを使用してarrが使用するメモリを追跡することをお勧めします。

于 2012-09-07T23:18:30.093 に答える
1

サンプルコードでは、のデストラクタmystructはの最後に呼び出されmainます。

ポインタポインタがスコープから外れると、ポイントされているオブジェクトには何も起こりません。オブジェクトの存続期間は、ポインタが存在しなかった場合に存在したであろうものにとどまります。もちろん、重要な詳細があります。/によって作成されたオブジェクトはd / newdになるまで存在し、によって割り当てられたメモリはdになるまで存在します。new[]deletedelete[]mallocfree

参照参照は、既存のオブジェクトの追加の名前にすぎません。const一時オブジェクトを指す参照を除いて、参照の有効期間は、参照先のオブジェクトの有効期間に影響を与えません。デストラクタは、そのオブジェクトが通常スコープから外れると呼び出されます(const一時オブジェクトへの参照は、参照がスコープから外れるまで一時を存続させconstます)。

「オブジェクト」という用語を使用することは単純化であり、ポインタまたは参照は実際にはメモリを指します。実際のオブジェクトを「追跡」することはありません。たとえば、ポインタがスコープから外れる前にポイントされているオブジェクトを破棄したり、参照がスコープから外れる前に参照されているオブジェクトを破棄したりすることができます。これらの無効なポインタ/参照は、それぞれ「ダングリングポインタ」および「ダングリング参照」と呼ばれます。

int* i = new int(5);
int& j = *i;
delete i;

// i is now a dangling pointer, and j is now a dangling reference
于 2012-09-07T23:25:36.753 に答える