5

コピー コンストラクターは、ポインターを使用したり、オブジェクトに動的にメモリを割り当てたりする必要がある場合など、多くの場合に使用されます。しかし、次の例を見てtutorialpoint.comください:

#include <iostream>

using namespace std;

class Line
{
public:
  int getLength( void );
  Line( int len );             // simple constructor
  Line( const Line &obj);  // copy constructor
  ~Line();                     // destructor

private:
  int *ptr;
};

// Member functions definitions including constructor
Line::Line(int len)
{
cout << "Normal constructor allocating ptr" << endl;
// allocate memory for the pointer;
ptr = new int;
*ptr = len;
}

Line::Line(const Line &obj)
{
cout << "Copy constructor allocating ptr." << endl;
ptr = new int;
*ptr = *obj.ptr; // copy the value
}

Line::~Line(void)
{
cout << "Freeing memory!" << endl;
delete ptr;
}
int Line::getLength( void )
{
return *ptr;
}

void display(Line obj)
{
   cout << "Length of line : " << obj.getLength() <<endl;
}

// Main function for the program
int main( )
{
   Line line(10);

   display(line);

  return 0;
}

結果は次のとおりです。

Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!

そして、(コピー コンストラクター) とデストラクタ内のコードをコメントアウトすると、同じ結果が得られました。

Normal constructor allocating ptr
Length of line : 10

では、ここでコピー コンストラクターを使用する場合と使用しない場合の違いは何ですか? また、なぜ「Freeing Memory!」2回発生?

4

4 に答える 4

4

解放されるメモリのアドレスを出力します。

コンパイラーがコンストラクターを生成し、ポインターを含むコンテンツの値のコピーを作成し、ポインターを二重に解放していて、ランタイムが文句を言っていないことを幸運に思っていることがわかると思います。

コンパイラによって生成されたコピー コンストラクターはまだ呼び出されています。その点に関しては何も変更されていません。作成していないため、そこから何も出力していません。

于 2012-08-23T20:54:39.320 に答える
3

関数への引数display()は値によって渡されるため、コンパイラはコピー コンストラクターを呼び出してそれを作成します。クラスがそのコピー コンストラクターを定義すると、正しいセマンティクスが得られます。コピー コンストラクターはコピーを作成し、そのコピーには長さを保持するための独自のメモリがあります。コピー コンストラクターを削除すると、コンパイラーによってコンストラクターが生成され、渡されるコピーにdisplay()は元のポインターと同じポインターが含まれます。そのコピーが破棄されると、ptr が指すメモリが削除されます。オリジナルが破壊されると、同じメモリが再び削除されます (目に見える影響はありません)。これは絶対に望んでいることではありません。そのため、コピー コンストラクターを定義する必要があります。@Joe が言うように: デストラクタ内で、「ptr」の値を出力して、これをより明確に確認します。

于 2012-08-23T21:10:07.853 に答える
0

次の形式の型 T のコンストラクタ

T (const & T);

単一の引数は、同じ型の既存のオブジェクトへの const 参照である必要があります 既存のオブジェクトの複製を作成します オブジェクトのコピーが必要な場合はいつでも使用されます 関数への引数、関数から返される結果を含める C++ でのポインターベースの配列の問題:–範囲チェックなし。== と意味のある比較はできません 配列の代入はありません (配列名は const ポインターです)。配列を関数に渡す場合、サイズは別の引数として渡す必要があります。

于 2014-01-15T09:37:40.703 に答える