2011-01-19 13 views
22

名前のない一時オブジェクトをconst refパラメータで定義された関数に渡しています。クラスのコピーctorがプライベートで、コンパイルエラーが発生します。このような状況でコピーコンストラクタが呼び出される理由はわかりません。const参照で一時的に渡すときにコピーコンストラクタが呼び出されるのはなぜですか?

class A { 
public: 
    A(int i) {} 
private: 
    A(const A&) {} 
}; 

void f(const A& a) 
{ 
} 

int main() 
{ 
    f(A(1)); // <-- error here: 'A::A(const A&)' is private 
} 

私はメインを変更すると、予想通り:

A a(1); 
f(a); 

それが動作します。

EDIT:(1)コンストラクタA(I int型)を呼び出した後、(定数A &)は&をCONST(Fを無効にするコールで呼び出されているため、コンパイラは4.1.2

+0

どのコンパイラを使用していますか? – sharptooth

+0

VC++ 9は最初の変種をコンパイルするのに満足しています。 – sharptooth

+0

@sharptooth:gcc、更新します – davka

答えて

17

あなたがC++標準は、一時的な オブジェクトがこの コンテキストとの コピーで満たされ、その内容で作成されるべきであると述べているCopy Constructor Needed with temp objectにあなたの質問への答えを見つけるか、http://gcc.gnu.org/bugs/#cxx%5Frvalbind

に直接行くことができます私たちが試みているオブジェクト 参照にバインドします。一時的なコピーを省略することができる とも言われていますが、コピーコンストラクタ の意味的制約(例: アクセシビリティ)はまだチェックする必要があります。詳細について

は、 C++標準の以下の段落に相談することができる:[dcl.init.ref]/5 弾丸2、サブ弾丸1、及び [class.temporary]/2。

GCC 4.3.0以降、GCCはもはや はこのケースではエラーを返しません。この の変更は、 C++言語委員会の意図に基づいています。 2010-05-28現在、C++ 0x標準の最終案案 はこの コードをエラーなしで許可します。

+2

+1! – Nawaz

0

gccのです)。

A(int i)コンストラクタを明示的にし、このエラーに直面しないでください。

編集:私は質問を誤解していると思います。私はこれを削除するかもしれない。

+0

** C++標準§3.2第2段落:** の実装によって実際に コールが省略された場合でもコピーコンストラクタが使用されます。 – dalle

+2

コピーコンストラクタは概念的にはここで呼び出されるべきではありません。それが問題のポイントです。参照渡しは新しいオブジェクトの作成を意味しないため、コピーはありません。 – sharptooth

+0

なぜ落選ですか?標準に従って、実際には正しいです。 – dalle

18

A(1)は、の値 5.2.3 [expr.type.conv]です。一時的に作成し、一時的にその式の値をコピーし、その一時的にその参照を結合することができる右辺コンパイラである式を有するconst基準(関数の引数)を初期化において

。 8.5.3 [dcl.init.ref]/5

[...]コピーを作成するために使用されるコンストラクタは、コピーが実際に行われたかどうかにかかわらず呼び出し可能でなければなりません。

この現象は、C++の次のバージョンで変更されたためです。新しい標準では、のprvalueから初期化されたconstの参照は、参照オブジェクトに直接バインドされなければなりません。この場合には一時的なものを作成することはできず、コピーコンストラクタは使用されないか、または必要とされません。

+0

+1が正しい!ありがとうございます。 – Nawaz

+0

あなたの最後の段落はなぜこれが新しいバージョンのgccで起こらないのかを@Nawazのコメントごとに説明します。 – davka

+0

@davka:それが理由だと思います、はい。良い情報のために+1 –

関連する問題