Est un =default
Le constructeur de déplacement est équivalent à un constructeur de déplacement par membre ?
Oui . Mise à jour : Eh bien, pas toujours. Regardez cet exemple :
#include <iostream>
struct nonmovable
{
nonmovable() = default;
nonmovable(const nonmovable &) = default;
nonmovable( nonmovable &&) = delete;
};
struct movable
{
movable() = default;
movable(const movable &) { std::cerr << "copy" << std::endl; }
movable( movable &&) { std::cerr << "move" << std::endl; }
};
struct has_nonmovable
{
movable a;
nonmovable b;
has_nonmovable() = default;
has_nonmovable(const has_nonmovable &) = default;
has_nonmovable( has_nonmovable &&) = default;
};
int main()
{
has_nonmovable c;
has_nonmovable d(std::move(c)); // prints copy
}
Il imprime :
copy
http://coliru.stacked-crooked.com/a/62c0a0aaec15b0eb
Vous avez déclaré le constructeur de déplacement par défaut, mais la copie se produit au lieu du déplacement. Pourquoi ? Parce que si une classe possède ne serait-ce qu'un seul membre non déplaçable, alors la fonction explicitement en défaut de paiement Le constructeur de mouvement est implicitement supprimé (quel jeu de mots). Donc, quand vous exécutez has_nonmovable d = std::move(c)
le constructeur de copie est en fait appelé, parce que le constructeur de déplacement de has_nonmovable
est supprimé (implicitement), il n'existe tout simplement pas (même si vous avez explicitement déclaré le constructeur move par l'expression has_nonmovable(has_nonmovable &&) = default
).
Mais si le constructeur de move de non_movable
n'a pas été déclaré du tout, le constructeur de move serait utilisé pour movable
(et pour chaque membre qui a le constructeur move) et le constructeur copy serait utilisé pour nonmovable
(et pour chaque membre qui ne définit pas le constructeur move). Voir l'exemple :
#include <iostream>
struct nonmovable
{
nonmovable() = default;
nonmovable(const nonmovable &) { std::cerr << "nonmovable::copy" << std::endl; }
//nonmovable( nonmovable &&) = delete;
};
struct movable
{
movable() = default;
movable(const movable &) { std::cerr << "movable::copy" << std::endl; }
movable( movable &&) { std::cerr << "movable::move" << std::endl; }
};
struct has_nonmovable
{
movable a;
nonmovable b;
has_nonmovable() = default;
has_nonmovable(const has_nonmovable &) = default;
has_nonmovable( has_nonmovable &&) = default;
};
int main()
{
has_nonmovable c;
has_nonmovable d(std::move(c));
}
Il imprime :
movable::move
nonmovable::copy
http://coliru.stacked-crooked.com/a/420cc6c80ddac407
Mise à jour : Mais si vous commentez la ligne has_nonmovable(has_nonmovable &&) = default;
alors la copie sera utilisée pour les deux membres : http://coliru.stacked-crooked.com/a/171fd0ce335327cd - des empreintes :
movable::copy
nonmovable::copy
Donc probablement en mettant =default
partout a encore du sens. Cela ne signifie pas que vos expressions de mouvement bougeront toujours, mais cela augmente les chances de le faire.
Une dernière mise à jour : Mais si l'on commente la ligne has_nonmovable(const has_nonmovable &) = default;
soit, alors le résultat sera :
movable::move
nonmovable::copy
Donc si vous voulez savoir ce qui se passe dans votre programme, faites tout par vous-même :sigh :