20
class MyClass
{
public:
  ~MyClass() {}
  MyClass():x(0), y(0){} //default constructor
  MyClass(int X, int Y):x(X), y(Y){} //user-defined constructor
  MyClass(const MyClass& tempObj):x(tempObj.x), y(tempObj.y){} //copy constructor

private:
  int x; int y;
};

int main()
{
  MyClass MyObj(MyClass(1, 2)); //user-defined constructor was called.
  MyClass MyObj2(MyObj); //copy constructor was called.
}

最初のケースでMyClass(1, 2)は、ユーザー定義コンストラクターを呼び出してオブジェクトを返すときにMyObj、コピーコンストラクターを呼び出すことを期待していました。の2番目のインスタンスのコピーコンストラクターを呼び出す必要がないのはなぜMyClassですか?

4

4 に答える 4

40

一時オブジェクトがコピーされ、その後破棄されるという唯一の目的で作成される場合は常に、コンパイラは一時オブジェクトを完全に削除し、結果を受信者で直接(つまり、コピーを受け取ることになっているオブジェクトで直接)構築することができます。あなたの場合

MyClass MyObj(MyClass(1, 2));

に変換することができます

MyClass MyObj(1, 2);

コピーコンストラクタに副作用がある場合でも。

このプロセスは、コピー操作の省略と呼ばれます。これは、言語標準の12.8/15で説明されています。

于 2010-09-07T23:40:45.770 に答える
19

このような場合、コピーコンストラクタは省略できます

同様にMyClass MyObj = MyClass( 1, 2 );

そしてと

std::string str = "hello";

このようなコードには、をに変換するための暗黙のコンストラクター呼び出しがchar*ありstd::stringます。

std::string str = std::string( "hello" ); // same, written more verbosely

コピーの省略がないと、代入構文による「簡単な」文字列の初期化により、追加のディープコピーが発生します。そして、その構文はあなたが持っているものと99%同等です。

于 2010-09-07T23:37:40.187 に答える
5

Potatoswatter と Andrey T. が言ったこととは別に、コンストラクターを省略しないようにほとんどのコンパイラーを誘導できることに注意してください。GCC は通常、必要な出力を提供する-fno-elide-constructorsMSVC を提供します。/Odここにいくつかのコードがあります:

#include <iostream>

#define LOG() std::cout << __PRETTY_FUNCTION__ << std::endl // change to __FUNCSIG__ on MSVC > 2003

class MyClass
{
public:
  ~MyClass() { LOG(); }
  MyClass():x(0), y(0){LOG(); } //default constructor
  MyClass(int X, int Y):x(X), y(Y){LOG(); } //user-defined constructor
  MyClass(const MyClass& tempObj):x(tempObj.x), y(tempObj.y){LOG(); } //copy constructor

private:
int x; int y;
};

int main()
{
 MyClass MyObj(MyClass(1, 2)); //User-defined constructor was called.
 MyClass MyObj2(MyObj); //Copy constructor was called.
}

MingW32 で GCC 4.5.0 でコンパイル:

 g++ -Wall -pedantic -ansi -pedantic tmp.cpp -o tmp -fno-elide-constructors

出力:

$ tmp.exe
MyClass::MyClass(int, int)
MyClass::MyClass(const MyClass&)
MyClass::~MyClass()
MyClass::MyClass(const MyClass&)
MyClass::~MyClass()
MyClass::~MyClass()
于 2010-09-08T00:01:59.273 に答える
2

何が呼び出されないと思いますか?これを試してください[編集:コピーコンストラクターの使用が省略されている場合でも可用性を確認する必要があるため、プライベートコピーコンストラクターを使用するようにコードを変更します]:

class MyClass
{
public:
   ~MyClass() {}
   MyClass():x(0), y(0){} //default constructor
   MyClass(int X, int Y):x(X), y(Y){} //user-defined constructor

private:
   MyClass(const MyClass& tempObj):x(tempObj.x), y(tempObj.y){} //copy constructor
   int x; int y;
};

int main()
{
    MyClass MyObj(MyClass(1, 2)); //User-defined constructor was called.
    MyClass MyObj2(MyObj); //Copy constructor was called.
}

これをコンパイルしようとすると、次の両方の行でエラーが発生しmainます。

myclass.cpp(17) : error C2248: 'MyClass::MyClass' : cannot access private member
 declared in class 'MyClass'
        myclass.cpp(11) : see declaration of 'MyClass::MyClass'
        myclass.cpp(4) : see declaration of 'MyClass'
myclass.cpp(18) : error C2248: 'MyClass::MyClass' : cannot access private member
 declared in class 'MyClass'
        myclass.cpp(11) : see declaration of 'MyClass::MyClass'
        myclass.cpp(4) : see declaration of 'MyClass'

概念的には、両方の場合にcopy ctorが使用され、コンパイラーはそれがアクセス可能であることを確認する必要があります。ただし、最初のケースでは、コンパイラーは、コピーコンストラクターを使用できる限り、実際の使用を自由に排除できます。

于 2010-09-07T23:40:07.670 に答える