EDIT:
Si: la move semantics è esplicita. Se non usi std::move, il compilatore userà il costruttore di copia e/o l'operatore di assegnamento che auto genera. Solo se esiste una reale rvalue il compilatore userà in automatico la move semantics.E questi ultimi li invoco esplicitamente utilizzando la funzione std::move quando li ho bisogno, giusto?
In (1) viene generata una rvalue dato che il compilatore deve creare una variabile temporanea di tipo Test come valore di ritorno. Pertanto sceglie in automatico il mctor.codice:class Test { int i; public: Test() : i(0) {}; Test(int k) : i(k) {}; Test(const Test& rhs) : i(rhs.i) {}; // cctor Test(Test&& rhs) : i(rhs.i) { // mctor rhs.i=0; }; }; Test g() { Test t(10); return t; } Test t = g(); // 1 Test k = t; // 2
In (2) invece non esplicitando la move semantics hai due lvalue, di conseguenza il compilatore dovrà scegliere il cctor.
Se commenti il cctor, il compilatore lo genera in automatico, se lo rendi privato (o delete nel tuo caso), il compilatore darà errore.
Se commenti il mctor, disabiliti la move semantics e il compilatore dovrà scegliere il cctor (o generarne uno se non lo hai disabilitato).
Il caso (1) è il tipico esempio di rvalue automatica, in tutti gli altri casi la move semantics deve essere esplicita.
Essendo uno dei cardini del C++11 è meglio capirla bene per trarne il massimo vantaggio.