Czy konstruktor ruchów powinien przyjmować stałe lub niestałe odniesienie do wartości rvalue?
W kilku miejscach widziałem zalecane podpisy konstruktorów kopiowania i przenoszenia podane jako:
struct T
{
T();
T(const T& other);
T(T&& other);
};
Gdzie konstruktor kopiowania przyjmuje stałą referencję, a konstruktor ruchu przyjmuje niestałe odniesienie do wartości rvalue.
O ile widzę, to uniemożliwia mi wykorzystanie semantyki ruchu podczas zwracania obiektów const z funkcji, jak w przypadku poniżej:
T generate_t()
{
const T t;
return t;
}
Testowanie tego z VC11 Beta,T
wywoływany jest konstruktor kopiowania, a nie konstruktor ruchu. Nawet używającreturn std::move(t);
konstruktor kopii jest nadal wywoływany.
Widzę, jak to ma sens, ponieważt
jest const, więc nie powinien się wiązaćT&&
. Za pomocąconst T&&
w ruchu podpis konstruktora działa dobrze i ma sens, ale wtedy masz problem, ponieważother
jest const, nie można zlikwidować jego członków, jeśli muszą zostać zlikwidowane - będzie działać tylko wtedy, gdy wszyscy członkowie są skalarami lub przenoszą konstruktory z odpowiednim podpisem.
Wygląda to na jedyny sposób, aby upewnić się, że konstruktor ruchu został wywołany w ogólnym przypadku, który ma zostać wykonanyt
w pierwszej kolejności non-const, ale nie lubię tego robić - budowanie rzeczy jest dobrą formą i nie oczekiwałbym klientaT
wiedzieć, że musieli się przeciwstawić tej formie, aby zwiększyć wydajność.
Myślę więc, że moje pytanie jest dwojakie; po pierwsze, czy konstruktor ruchów powinien przyjmować stałe lub niestałe odniesienie do wartości rvalue? Po drugie: czy mam rację w tej linii rozumowania? Że powinienem przestać zwracać rzeczy, które są stałe?