En C++, on distingue l'initialisation directe (direct) et l'initialisation indirecte (copy) des objets :
Initialisation directe :
MyClass obj(arg1, arg2); int x(5);
Pour les classes, cela appelle directement le constructeur approprié.
Initialisation indirecte :
MyClass obj = MyClass(arg1, arg2); int x = 5;
Cela crée un objet temporaire, puis le copie (ou le déplace) (utilise le constructeur de copie / de déplacement).
Différences :
Exemple :
struct NonCopyable { NonCopyable(int) {} NonCopyable(const NonCopyable&) = delete; }; NonCopyable a(5); // OK : direct NonCopyable b = NonCopyable(5); // OK avec optimisation, erreur avant C++17 sans elle NonCopyable c = 5; // Erreur : pas de constructeur de copie
"L'initialisation par copie peut-elle provoquer plus d'appels de constructeurs que l'initialisation directe, si C++11 est utilisé avec un compilateur optimiseur ?"
Réponse : Théoriquement — oui. Sans l'élimination de copie, l'initialisation par copie crée un objet temporaire, puis appelle le constructeur de copie ou de déplacement. L'initialisation directe appelle toujours uniquement le constructeur principal. Cependant, les compilateurs modernes avec optimisation (C++17 et plus) éliminent cette différence grâce à l'élimination de copie garantie.
Histoire
Dans un projet financier, on a utilisé l'initialisation par copie avec un objet temporaire, alors que le type requis n'avait pas de constructeur de copie. L'application ne se compilait pas sur les anciens compilateurs (avant C++17), alors que l'initialisation directe fonctionnait.
Histoire
Dans un utilitaire de sérialisation de données, les programmeurs pensaient que l'initialisation directe et l'initialisation par copie étaient équivalentes. En conséquence, des copies inutiles de grandes structures ont eu lieu, entraînant des baisses de performances.
Histoire
Lors de l'initialisation de tableaux globaux d'objets utilisateur, l'initialisation indirecte a été utilisée. Les erreurs apparaissaient uniquement sur une plateforme, où l'élimination de copie ne se produisait pas, entraînant des appels implicites de constructeurs supplémentaires en raison des particularités de l'ABI.