2012-04-20 14 views
5

Ho scritto il seguente codice per capire la semantica del movimento. Funziona come previsto (cioè senza copie e solo mosse) in g ++ - 4.6 ma non in g ++ - 4.7.0. Ho pensato che fosse un bug nel collegamento in g ++ - 4.7.0 ma questo link dice che non è un bug in g ++ - 4.7. Quindi, come inteso da me dal link precedente, ho fatto il movimento di costruzione del nothrow ma ancora fa solo delle copie. Tuttavia, se faccio il nothrow del costruttore di copie, solo le mosse prendono posto. Qualcuno può spiegarlo?vector, move semantics, nothrow e 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; 
} 

risposta

5

In che modo "stai facendo la svolta al costruttore nothrow"? Con g ++ 4.7, se annoto il costruttore di move con noexcept allora il tuo esempio si sposta solo:

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

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

Grazie. L'ho scritto come 'S (nothrow) (S && ​​x) {....}'. Ma qual è la differenza tra queste due versioni "nothrow"? – suresh

+1

'noexcept' è la parola chiave C++ 11 per contrassegnare qualcosa come non-lancio. La firma che hai usato dichiara una funzione chiamata 'nothrow' che prende un' S' per ref valore e restituisce un valore 'S' per valore. –

+0

Questo spiega perché contrassegnare il costruttore di copie in questo modo fa sì che g + + 4.7 usi il costruttore di mosse: la tua classe non ha più ** un costruttore di copie (ma una funzione chiamata 'nothrow'), poiché g ++ 4.7 segue il" don " t genera implicitamente un costruttore di copia se c'è una regola di costruzione del movimento, quindi 'std :: vector' deve usare il costruttore di movimento. –