6

次のコードがコンパイルされない理由を説明できますか?

#include <iostream>

using namespace std;

class Foo
{
public:
  Foo() { cout << "Foo::Foo()" << endl << endl; }
  Foo& operator=(const Foo&) { cout << "Foo::operator=(const Foo&)" << endl << endl; }
private:
  Foo(const Foo& b) { *this = b; cout << "Foo::Foo(const Foo&)" << endl << endl; }
};

int main()
{
  Foo foo;

  foo = Foo();
}

私が受け取るエラー:

$ g++ -o copy_ctor_assign copy_ctor_assign.cc && ./copy_ctor_assign
copy_ctor_assign.cc: In function 'int main()':
copy_ctor_assign.cc:10: error: 'Foo::Foo(const Foo&)' is private
copy_ctor_assign.cc:17: error: within this context

注: private:キーワードを削除すると、コードはコンパイルされますが、コピー ctor は呼び出されません。では、プライベートの場合にエラーになるのはなぜですか?

それが重要かどうかはわかりませんが、私は使用しています:

$ g++ --version
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44)
Copyright (C) 2006 Free Software Foundation, Inc.
4

6 に答える 6

5

一時的な参照を初期化しています。
標準は次
のように述べています:一時は初期化する必要があります(8.5.3 par 5)「非参照コピー初期化のルールを使用して(8.5)」。

コピー構造は一時的に削除されます (標準で許可されています。12.8 par 5)。
ただし、標準は明確に述べています (12.2 パー 1):
「一時オブジェクトの作成が回避された場合でも (12.8)、一時オブジェクトが作成されたかのように、すべてのセマンティック制限を尊重する必要があります。[例: コピー コンストラクターがが呼び出されない場合、アクセシビリティ (第 11 節) などのすべての意味上の制限が満たされる必要があります。]"

(また、正しい引用を探しているときに、この重複が見つかりました:)

編集:標準から関連する場所を追加する

于 2009-10-13T16:45:17.793 に答える
4

そのコードは、gcc 4.3.3 および 4.4.1 でコンパイルされます。多分それは gcc 4.1 の単なるバグでしょうか?

于 2009-10-13T15:48:36.943 に答える
3

あなたが投稿したコードがプロジェクト内の唯一のコードであり、値による Foos の秘密の受け渡しがどこにも行われていないと仮定すると、gcc が最適化されていることがわかります。

Foo foo;
foo = Foo();

Foo foo = Foo();

...最初の形式はデフォルト構成と割り当てであり、2番目の形式は次と同等であるため、これは不健全です

Foo foo(Foo());

...これは明らかにコピー構築です。私が正しければ、コピー コンストラクターは実行されていません。これは、GCC が冗長な一時的なものを最適化できるためです。これは C++ 仕様で許可されています。

一般に、代入演算子とコピー コンストラクターを異なる保護レベルで使用することはお勧めできません。これまで見てきたように、結果は直感的でない場合があります。

于 2009-10-13T15:42:25.493 に答える
1

Copy Ctor は次の場合に呼び出されます。

  1. オブジェクトをパラメータとして値渡しで関数に渡します。
  2. 関数からオブジェクトを返します。

したがって、コードのどこかでこれらのケースのいずれかまたは両方を確実に実行しています。Copy Ctor を public に設定するか、前の 2 つのケースを回避する必要があります。

于 2009-10-13T15:38:29.433 に答える
0

次のように記述した場合、コピー コンストラクターが呼び出されます。

Foo foo; // normal constructor
Foo foo1(foo); //copy constructor

あなたの場合、最初にデフォルトのコンストラクターが呼び出され、次に operator= メソッドが呼び出されます。

于 2009-10-13T15:39:31.100 に答える
-1
#include <iostream>

using namespace std;

class Foo
{
public:
  Foo() { cout << "Foo::Foo()" << endl << endl; }
  Foo& operator=(const Foo&) { cout << "Foo::operator=(const Foo&)" << endl << endl; }
  Foo(const Foo& b) { *this = b; cout << "Foo::Foo(const Foo&)" << endl << endl; }
};

int main()
{
  Foo f1;// default constructor called

  Foo f2 = f1; //copy constructor called
}

これを確認してくださいFoo f2=f1;(f2はコピー コンストラクターを使用して作成されます)

于 2009-10-13T15:49:56.253 に答える