La différence entre les deux est vraiment très subtile. C++11 introduit la fonctionnalité de liste d'initialisation (aussi parfois appelée accolade de l'initialisation):
Avant C++11, lorsque vous voulez par défaut-construction de l'objet et de l' o
de type Obj
et de construire un Position p
de o
, vous avez eu à l'écrire
Obj o; // default construct o
Obj::Position p(o); // construct p using Position(Obj const&)
Une erreur commune pour les débutants (surtout avec un Java de fond) afin d'essayer d'écrire ceci:
Obj o(); // mistake: declares a function o returning an Obj
Obj::Position p(o); // error: no constructor takes a function
La première ligne déclare une fonction, et la deuxième, on essaie de créer un Position
à l'aide d'un constructeur qui prend un pointeur de fonction en argument. Afin de disposer d'un uniforme de l'initialiseur de la syntaxe de C++11 introduit initialisation de la liste:
Obj oo{}; // new in C++11: default construct o of type Obj
Obj::Position p1(oo); // possible before (and after) C++11
Obj::Position p2{oo}; // new in C++11: construct p2 using Position(Obj const&)
Cette nouvelle syntaxe fonctionne également en return
-états, ce qui conduit à la réponse de votre question: la différence entre return {*this};
et return *this;
, c'est que l'ancien initialise la valeur de retour directement à partir de *this
, tandis que le second se convertit *this
temporairement Position
objet, puis initialise la valeur de retour indirectement à partir de ce temporaire, qui échoue en raison à la fois la copie et déplacement-constructeur ont été explicitement supprimé.
Comme les précédentes affiches ont noté, la plupart des compilateurs éluder ces objets temporaires parce qu'ils ne sont pas vraiment utile pour quoi que ce soit; mais cela n'est possible que si ils pourraient être utilisés dans la théorie, soit parce que d'une copie ou d'un constructeur de déplacement est disponible. Parce que cela conduit à beaucoup de confusion (pourquoi ai-je besoin des accolades autour de mon retour? est le compilateur va éluder la copie ou pas?), C++17 fait disparaître ces inutiles temporaires, et initialise la valeur de retour directement dans les deux cas (return {*this};
et return *this
).
Vous pouvez essayer ceci à l'aide d'un compilateur qui prend en charge le C++17. Dans clang 4.0 ou gcc 7.1, vous pouvez passer --std=c++1z
, et de votre code devrait compiler amende avec ou sans bretelles.