2012-11-15 4 views
10

ルック:C++で合成された移動コンストラクタは、揮発性および仮想メンバーの影響を受けますか?次のコードで

struct node 
{ 

    node(); 
    //node(const node&); //#1 
    //node(node&&);   //#2 

    virtual     //#3 
    ~node(); 

    node* 
    volatile    //#4 
    next; 

}; 

int main() 
{ 

    node m(node());   //#5 
    node n=node();   //#6 
} 

でコンパイルされたときにはgcc-4.6.1、それは次のエラー生成します。私は、コンパイラはデフォルトの動きを作成するために失敗した理解したり、上のコンストラクタをコピーしたよう

g++ -g --std=c++0x -c -o node.o node.cc 
node.cc: In constructor node::node(node&&): 
node.cc:3:8: error: expression node::next has side-effects 
node.cc: In function int main(): 
node.cc:18:14: note: synthesized method node::node(node&&) first required here 

を私は行#1または#2のいずれかをコメント解除する場合、それは罰金をコンパイルする、それは明らかです。コードは、C++ 0xオプションなしで正常にコンパイルされるため、エラーはデフォルトの移動コンストラクタに関連しています。

しかし、ノードクラスではデフォルトの移動コンストラクタを作成できません。 #3または#4の行のいずれかにコメントすると(つまり、デストラクタを非仮想にするか、データメンバを不揮発にする)、再びコンパイルします。したがって、これら2つの組み合わせによってコンパイルされませんか?

もう1つのパズル、ライン#5はコンパイルエラーを起こさない、ライン#6とは何ですか? gccではすべて固有ですか? gcc-4.6.1?

+1

あなたは 'main'の復帰型skippyを忘れました –

答えて

12

[C++11: 12.8/9]:If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

  • X does not have a user-declared copy constructor,
  • X does not have a user-declared copy assignment operator,
  • X does not have a user-declared move assignment operator,
  • X does not have a user-declared destructor, and
  • the move constructor would not be implicitly defined as deleted.

[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. —end note ]

あなたの#3が合成を破っている理由です。

さらにit's far from clearvolatile types (including your node* volatile) are trivially copyable; it is implementation-defined whether they are or notと結論付けることができ、あなたのケースではそうではないようです。

非常に少なくとも

、私は先に行き推測できるv4.6.1にバックポートするための提案とV4.7でGCC made it stop working quite deliberately、...だから

、与えられた次

[C++11: 12.8/11]: An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/move constructor for a class X is defined as deleted (8.4.3) if X has:

  • a variant member with a non-trivial corresponding constructor and X is a union-like class, a non-static data member of class type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M ’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
  • a direct or virtual base class B that cannot be copied/moved because overload resolution (13.3), as applied to B ’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
  • any direct or virtual base class or non-static data member of a type with a destructor that is deleted or inaccessible from the defaulted constructor,
  • for the copy constructor, a non-static data member of rvalue reference type, or
  • for the move constructor, a non-static data member or direct or virtual base class with a type that does not have a move constructor and is not trivially copyable.

...#4が#3とは独立して#4も合成を破っている理由です。 #5については、それが実際には全くnodeの宣言が、それはnodeの建設に関連する症状を再生していない理由ですm —と呼ばれる関数の宣言(これはMost Vexing Parseとして知られている)ではありません

+0

ありがとうございます、あなたはそれを非常に明確にしました。まだ私が困惑しているのは、このコードがうまく動作するということです。 – user1827766

+0

まだ私が困惑しているのは、このコードがうまく動作することです:struct node {〜node();ノード*揮発性next; };これはまた:struct node {virtual〜node();}ノード* next; }; gcc-4.6.1では、揮発性データメンバやデストラクタを持つクラスの移動が可能ですが、何らかの形で仮想dtor/volatileデータメンバの組み合わせに不満があります。 – user1827766

+0

私は揮発性の問題が単純にコピー可能であるかどうかは、いくつかの実装がそれを与えたいと思っている原子意味論だけではないかと思います。もしそうなら、その変更は適切ではないように思えます。なぜなら、ISO C++では、volatileにアトミックセマンティクスがないからです。 – bames53