0

私は C++ で RVO について少し読んでいて、奇妙な観察結果を見つけました。以下のコードを実行しました..

class myClass {
  private:
    int *ptr;
    static int id;

  public:
    myClass() {
      id++;
      ptr = new int[10];
      printf("Created %p id %d this %p\n", ptr, id, this);
    }

    ~myClass() {
      delete[] ptr;
      ptr = NULL;
      printf("Deleted ptr id %d this %p\n", this->id, this);
      id--;
    }
};

int myClass::id = 0;

myClass testFunc(myClass var) {
  myClass temp;
  return temp;
}

int main() {
  myClass var1, var2;

  testFunc(var1);

  return 0;
}

私はo / pを取得しました

Created 0x9b14008 id 1 this 0xbfe3e910
Created 0x9b14038 id 2 this 0xbfe3e914
Created 0x9b14068 id 3 this 0xbfe3e91c
Deleted ptr id 3 this 0xbfe3e91c
Deleted ptr id 2 this 0xbfe3e918
Deleted ptr id 1 this 0xbfe3e914
Deleted ptr id 0 this 0xbfe3e910

testFunc への呼び出しの一時的なコピー変数は、実際にはいくつかの問題を引き起こします。var1 の ptr メンバーを削除します。これは、ポインタ 0xbfe3e918 のデストラクタへの呼び出しで確認できます。valgring の下では、このコードはメモリ リークを示しませんが、delete[] は無効です。

余分なデストラクタがどのように呼び出されているのか、対応するコンストラクタが同じものを呼び出さないのはなぜなのか、少し混乱しました??

4

3 に答える 3

0

var1関数の引数として値を渡すと、コピーが作成されます。これは (暗黙的に定義された) コピー コンストラクターで行われます。これが、プログラムが何も出力しない理由です。デフォルト コンストラクターで何かを出力するだけです。

ここで大きな問題が発生します。オブジェクトの両方のコピーに同じ配列へのポインターが含まれており、両方が破棄されると削除しようとします。この二重の削除はエラーであり、未定義の動作を引き起こします。

これを修正するには、3 つのルールに従って、クラスを正しくコピー可能 (またはコピー不可) にします。または、この危険な生メモリのいじくり回しをすべて停止し、std::vectorまたは同様のものを使用して、配列を正しく管理します。

于 2014-08-30T16:23:19.400 に答える