2012-12-16 4 views
7

は、次のコードを考えてみましょう:リファレンスに一時的にバインディングするには、C++でコピーコンストラクタが必要ですか?

​​

このコードは、GCC 4.7.2と罰金コンパイルしますが、次のエラーでのVisual C++ 2010でコンパイルに失敗します。

test.cc(8) : error C2248: 'A::A' : cannot access private member declared in class 'A' 
     test.cc(2) : see declaration of 'A::A' 
     test.cc(1) : see declaration of 'A' 

だから、それが持っていることが必要です一時的に参照にバインドするときにアクセスできるコピーコンストラクタ

これが私の前の質問に多少関連している:

Is there a way to disable binding a temporary to a const reference?

+0

はい、コピーctorはプライベートであり、意図的に実装されていません。 – vitaut

+0

ちょうど 'A()を試しましたか? '関数内から戻り値にコピーコンストラクタをコピーする必要がある可能性があります。 –

+0

Visual C++ 2012はコードを受け入れます。 –

答えて

4

So is it necessary to have a copy constructor accessible when binding a temporary to a reference?

ポストC++ 11 - ノー
事前C++ 11 - はい。


このコードは、C++ 11標準に準拠しているため、GCC 4.7.2で正常にコンパイルされます。

標準では、const参照がprvalueから初期化されるとき、参照オブジェクトに直接バインドされなければならず、一時的なオブジェクトの作成は許可されません。また、コピーコンストラクタは使用されていないか、または必須ではありません。

C++ 11以前は、ルールが異なりました。そして、この動作(コピーコンストラクタがと呼ばれるかどうか)は実装定義です。 C++ 03は、const参照を一時的なものにバインドしている間に呼び出されるコピーコンストラクタを許可したため、コピーコンストラクタにアクセス可能である必要があります。 Visual C++ 2010はC++ 03標準に準拠しています。

+0

"この動作は定義された実装でした"というのは少し誤解を招くことです。実際のコピーは実装定義であったが、C++ 03標準ではアクセス可能なコピーコンストラクタが必要であった。 –

+0

@ Cheersandhth.-Alf:編集してより明瞭にする。 –

+1

"C++ 11標準では、const参照がprvalueから初期化されるとき、参照オブジェクトに直接バインドされなければならず、一時的なオブジェクトの作成は許可されていないことを要求しています。私たちは少し誤解を招く。直接バインディングが可能なタイプの場合にのみ保持されます。言い換えれば、ルールは変換を妨げるものではありません。 –

0

のVisual C++が間違っています。標準は、コピーコンストラクタが一時的な参照への参照をバインドするためにアクセス可能でなければならないことを示していない。これは実装定義であることをC++ 03標準状態の

2

セクション8.5.3.5:

If the initializer expression is an rvalue, with T2 a class type, and "cv1 T1" is reference-compatible with "cv2 T2," the reference is bound in one of the following ways (the choice is implementation-defined):

-- The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.

-- A temporary of type "cv1 T2" [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a sub-object within the temporary.

The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.

だから、両方の実装はC++ 03標準と一致していることが表示されます。

最後の文は少し混乱しますが、私が読んだところでは、実装は2番目の方法を選択することができますが、依然としてコピーを最適化することを意味します。その場合、コピーコンストラクターは、戻り値の最適化と同様に、コピーが実際には実行されなかったとしてもアクセス可能でなければなりません。

C++ 11標準では、2番目の方法はもはやオプションではありません。

+4

C++ 03はC++ 11に置き換えられ、C++ 11ではルールが変更されました。 –

+0

それは私が探していたものです。ありがとう。 – vitaut

+0

@ Vaughn Cato:唯一のことは、あなたの最後の声明が、あなたが引用した基準からの最後の声明と矛盾することです。 IIUCでは、両方のケースでコピー・コータが使用可能であるべきであるとGCCが新しい標準のルールまたはそのバグを使用している可能性があることを標準で示しています。 – vitaut

関連する問題