Ho seguente classeriferimenti rvalue senza std :: muovono
class widget {
// The methods only print their name, i.e. c'tor, destructor etc.
public:
widget();
widget(const widget&);
widget(widget&&);
~widget();
auto operator=(const widget&) -> widget&;
auto operator=(widget&&) -> widget&;
};
che uso nel seguente codice
#include "widget.h"
auto main() -> int {
widget c(std::move(widget()));
c = std::move(widget());
return 0;
};
Il comportamento risultante è comprensibile per me. Nella prima chiamata viene costruito un widget, quindi il costruttore di movimento viene richiamato e il distruttore viene chiamato sul widget temporaneo.
La seconda chiamata fa la stessa cosa, si aspetta di chiamare l'operatore di assegnazione del movimento invece del costruttore di movimento. Lasciando il metodo principale, il distruttore viene richiamato su c
.
Ora arriva la parte interessante:
#include "widget.h"
auto main() -> int {
widget c((widget()));
c = widget();
return 0;
};
Se lascio la chiamata al std::move
, il primo caso smette di funzionare e si traduce in una sola chiamata al costruttore. Mentre il secondo caso funziona ancora come prima.
Cosa mi manca qui? Perché queste due chiamate di funzione trattano i loro parametri in modo diverso? Ho provato questo su gcc e clang.
'(widghet())' è un valore di prvalore, cioè un valore, quindi viene spostato (se possibile). 'std :: move' non si sposta, cambia solo la categoria di valore di un'espressione. Se quell'espressione avesse comunque la corrispondente categoria di valore, sarebbe superfluo. – Columbo
Le parentesi sono necessarie, altrimenti l'espressione viene valutata come puntatore di funzione a una funzione che non accetta parametri e restituisce un 'widget'. – mike
Potrebbe essere che il compilatore stia ottimizzando alcune costruzioni e copie per te? –