2012-04-20 10 views
5

私は、移動セマンティクスを理解するために次のコードを書いています。これは、g ++ - 4.6では期待通りに動作します(つまり、コピーはなく、移動のみ)が、g ++ - 4.7.0では動作しません。私はそれがg ++でのリンクのバグだと思った - 4.7.0しかし、これはg ++ - 4.7のバグではないことをこのlinkは言う。だから、上記のリンクから私が理解しているように、私は移動コンストラクタをnothrowにしましたが、それでもコピーだけを行います。しかし、コピーコンストラクタをnothrowにすると、移動だけが行われます。誰かがこれを説明できますか?vector、move semantics、nothrow and g ++ 4.7

#include <iostream> 
#include <vector> 
using namespace std; 

struct S{ 
int v; 
static int ccount, mcount; 
S(){} 
    //no throw constructor 
    //S(nothrow)(const S & x){ 
S(const S & x){ 
    v = x.v; 
    S::ccount++; 
} 
S(S&& x){ 
    v = x.v; 
    S::mcount++; 
} 
}; 

int S::ccount = 0; 
int S::mcount = 0; 
int main(){ 

vector<S> v; 
S s; 

for(int i = 0; i < 10; i++) { 
    v.push_back(std::move(s)); 
} 

cout << "no of moves = " << s.mcount << endl; 
cout << "no of copies = " << s.ccount << endl; 
return 0; 
} 

答えて

5

どのように「移動コンストラクタを使用しないでください」ですか? g ++ 4.7では、移動コンストラクタにnoexceptという注釈を付けると、あなたの例は移動するだけです。

S(S&& x) noexcept{ ... } 

no of moves = 25 
no of copies = 0 
+0

ありがとうございました。私は 'S(nothrow)(S && x){....}'と書いた。しかし、この2つの "nothrow"バージョンの違いは何ですか? – suresh

+1

'noexcept'は何かを投げていないとマークするためのC++ 11のキーワードです。あなたが使用したシグネチャは、 'nothrow'という関数を宣言しています。これはrvalue refで' S 'をとり、値で 'S'を返します。 –

+0

これは、この方法でコピーコンストラクタをマークすると、g ++ 4.7はmoveコンストラクタを使用する理由が説明されています.g ++ 4.7は "don 'の後に**コピーコンストラクタ(ただし' nothrow'という関数)移動コンストラクタがある場合には暗黙的にコピーコンストラクタを生成するので、 'std :: vector'は移動コンストラクタを使用しなければなりません。 –