J'ai ce morceau de code:std :: vecteur d'initialisation mouvement/constructeur de copie de l'élément
#include <iostream>
#include <vector>
using namespace std;
class Foo{
public:
Foo() noexcept {cout << "ctor" << endl;}
Foo(const Foo&) noexcept {cout << "copy ctor" << endl;}
Foo(Foo&&) noexcept {cout << "move ctor" << endl;}
Foo& operator=(Foo&&) noexcept {cout << "move assn" << endl; return *this;}
Foo& operator=(const Foo&) noexcept {cout << "copy assn" << endl; return *this;}
~Foo() noexcept {cout << "dtor" << endl;}
};
int main()
{
Foo foo;
vector<Foo> v;
v.push_back(std::move(foo));
// comment the above 2 lines and replace by
// vector<Foo> v{std::move(foo)};
}
La sortie est ce que je pense (compilé avec g++ -std=c++11 --no-elide-constructors
, même sortie sans le drapeau)
ctor
move ctor
dtor
dtor
maintenant au lieu d'utiliser directement push_back
initialiser le vecteur v
comme
vector<Foo> v{std::move(foo)};
Je ne comprends pas pourquoi je reçois les sorties:
1) (sans --no-elide-constructors
)
ctor
move ctor
copy ctor
dtor
dtor
dtor
2) (avec --no-elide-constructors
)
ctor
move ctor
move ctor
copy ctor
dtor
dtor
dtor
dtor
Dans le premier cas, pourquoi la Copier ctor invoqué? Et dans le second cas, quand le compilateur n'effectue pas d'élision, je n'ai absolument aucune idée de pourquoi le mouvement ctor est invoqué deux fois. Des idées?
Ohhh, j'ai compris ... La syntaxe '{...}' pour l'initialisation uniforme est assez compliquée, et j'ai maintenant réalisé que 'vector' n'est pas un agrégat. Et oui, même sur mon clang, pas de mouvement supplémentaire. Bonne réponse, merci! – vsoftco
Je suis d'accord avec T.C .: le fait que gcc produise deux appels constructeurs de mouvement semble être un bug. Mais je suppose que tant que ce comportement n'est observable que lorsque vous passez '-fno-elide-constructors', il n'y a pas de problème. – Brian
La réponse de T.C. le cloue, je suis d'accord que le comportement de clang semble correct. Le code suivant devrait être le même: 'Foo arr [1] = {std :: move (foo)}; vecteur v (arr, arr + 1); Le 'initializer_list' devrait seulement servir à maintenir' arr' et 'arr + 1', ne pas déplacer/copier les éléments. –