30 votes

Initialisation de la valeur d'un objet automatique ?

Je suis en train d'écrire une classe template et à un moment de mon code, j'aimerais pouvoir initialiser un objet du type paramétré sur la pile. Pour l'instant, j'y parviens en écrivant quelque chose comme ceci :

template <typename T> void MyClass<T>::doSomething() {
    T valueInitialized = T();
    /* ... */
}

Ce code fonctionne, mais (à moins que le compilateur ne soit intelligent) il nécessite la création et la destruction inutiles du fichier temporaire T objet. Ce que je voudrais écrire est ce qui suit, que je sais être incorrect :

template <typename T> void MyClass<T>::doSomething() {
    T valueInitialized(); // WRONG: This is a prototype!
    /* ... */
}

Ma question est de savoir s'il existe un moyen efficace d'initialiser la valeur de l'objet automatique sans avoir à construire explicitement un objet temporaire et à l'assigner à l'objet automatique. Est-ce possible ? Ou est-ce que T var = T(); aussi bon qu'il puisse l'être ?

0 votes

Bonne question :) (Bien que vous devriez savoir qu'il ne faut pas remercier dans un corps de question !)

0 votes

Par curiosité, en quoi cela pose-t-il problème ? Si T est un type défini par l'utilisateur, il doit avoir un constructeur par défaut. S'il s'agit d'un type intrinsèque, la perte de performance due à la construction par copie devrait être négligeable. Même en supposant que le compilateur ne l'optimisera pas.

0 votes

@Maxpm- C'est surtout par curiosité. J'ai toujours utilisé l'option T var = T(); et s'est dit qu'il y avait probablement une façon plus propre de procéder. Vous avez tout à fait raison de dire que l'impact sur les performances devrait être négligeable.

24voto

ildjarn Points 38377

Les utilisations suivantes Copie-initialisation ce qui est "probablement bien" dans 95 % des cas en C++03 :

T var = T();

Mais pour générique (C++03), vous devriez toujours préférer le code initialisation directe pour tenir compte des 5 % restants :

T var((T())); // extra parentheses avoid the most vexing parse – the extra parentheses
              // force the contents to be evaluated as an expression, thus implicitly
              // *not* as a declaration.

Ou mieux encore, utilisez la fonction Boost . Utility.ValueInit qui regroupe le comportement idéal pour vous ainsi que des solutions de contournement pour diverses déficiences du compilateur (malheureusement, plus nombreuses qu'on ne le pense) :

boost::value_initialized<T> var;

En C++11, il est possible d'utiliser la syntaxe d'initialisation de liste pour réaliser l'initialisation de valeur directe d'une manière nettement moins bruyante :

T var{}; // unambiguously value-initialization†

( † N.B. : techniquement, cette procédure invoquera le principe du std::initializer_list<> au lieu de procéder à l'initialisation de la valeur pour certains types pathologiques. On peut supposer que le résultat net devrait être le même).

8 votes

Ugh, on dirait du LISP. :) Cela fonctionne-t-il vraiment avec tous les types d'animaux ? +1 de ma part pour avoir suggéré une bibliothèque d'appoint.

0 votes

Oui, il fonctionne avec tous les types de produits. Les parenthèses sont bénignes et permettent de désambiguïser la déclaration.

0 votes

À moins que je n'interprète mal la différence entre l'initialisation directe et l'initialisation par copie, cela n'a d'incidence que sur l'autorisation des constructeurs de conversion, et non sur la création d'un objet temporaire. Est-ce exact ? Si oui, quel avantage cette approche particulière offre-t-elle par rapport à la version initialisée par copie ?

16voto

FredOverflow Points 88201

Vous pouvez utiliser des accolades en C++0x :

T valueInitialized{};

0 votes

Ah, je n'avais pas pensé à C++11 ! +1 de moi !

5voto

sbi Points 100828

Non, il n'y a pas d'autre moyen d'initialiser de manière fiable un type template en C++03.

Si vous pouvez compter sur T n'étant que des types de classes avec des constructeurs par défaut, vous pourriez simplement écrire

T valueInitialized;

mais si T pourrait tout aussi bien être un type intégré,

T valueInitialized = T();

est la voie à suivre.

Avez-vous une raison de ne pas faire confiance à votre compilateur pour optimiser cette copie ?

1 votes

Oh, je fais absolument confiance au compilateur pour le faire :-) Il s'agit surtout de savoir s'il existe une façon plus élégante de procéder qui ne dépende pas d'un auteur de compilateur intelligent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X