Comme les commentaires l'ont noté, vous ne pouvez pas réellement "déplacer" quoi que ce soit hors de l'objet argument, parce qu'il est const (du moins, pas sans un cast const, qui est une mauvaise idée car il pourrait conduire à UB). Donc, il est clair que ce n'est pas utile pour le simple fait de déplacer. Le but de la sémantique de déplacement est de fournir une optimisation des performances, et ce n'est pas le cas ici, alors pourquoi le faire ?
Cela dit, je ne vois que deux cas où cela est utile. Le premier concerne les constructeurs "gourmands" :
#include <iostream>
struct Foo {
Foo() = default;
Foo(const Foo&) { std::cerr << "copy constructor"; }
Foo(Foo&&) { std::cerr << "copy constructor"; }
template <class T>
Foo(T&&) { std::cerr << "forward"; }
};
const Foo bar() { return Foo{}; }
int main() {
Foo f2(bar());
return 0;
}
Ce programme imprime "forward". La raison en est que le type déduit dans le modèle sera const Foo
ce qui permet une meilleure adéquation. Cela se produit également lorsque vous avez des constructeurs variadiques à transmission parfaite. Commun pour les objets proxy. Bien sûr, retourner par une valeur constante est une mauvaise pratique, mais strictement parlant, ce n'est pas incorrect, et cela peut casser votre classe. Donc vous devriez vraiment fournir un Foo(const Foo&&)
(qui délègue simplement au constructeur de copie) ; pensez-y comme si vous mettiez un point sur un t ou un point sur un i lorsque vous écrivez du code générique de haute qualité.
Le second cas se présente lorsque vous souhaitez supprimer explicitement les constructeurs de déplacement, ou un opérateur de conversion de déplacement :
struct Baz {
Baz() = default;
Baz(const Baz&) = default;
Baz(Baz&&) = delete;
};
const Baz zwug() { return {}; }
int main() {
Baz b2(zwug());
}
Ce programme se compile donc l'auteur a échoué dans sa mission. La raison en est que les surcharges de const ref correspondent à des const rvalues, et que la construction de const rvalue n'a pas été explicitement supprimée. Si vous voulez supprimer les déplacements, vous devrez également supprimer la surcharge const rvalue.
Le deuxième exemple peut sembler très obscur, mais disons que vous écrivez une classe qui fournit une vue d'une chaîne de caractères. Vous ne voudrez peut-être pas permettre qu'elle soit construite à partir d'une chaîne temporaire, car vous courrez un plus grand risque que la vue soit corrompue.