Lors de l'utilisation de l'attache-clos de l'initialiseur?
En C++11, nous avons que la nouvelle syntaxe pour initialiser les classes qui nous donne un grand nombre de possibilités pour initialiser des variables.
{ //Example 1
int b(1);
int a{1};
int c = 1;
int d = {1};
}
{ //Example 2
std::complex<double> b(3,4);
std::complex<double> a{3,4};
std::complex<double> c = {3,4};
auto d = std::complex<double>(3,4);
auto e = std::complex<double>{3,4};
}
{ //Example 3
std::string a(3,'x');
std::string b{3,'x'}; //oops
}
{ //Example 4
std::function<int(int,int)> a(std::plus<int>());
std::function<int(int,int)> b{std::plus<int>()};
}
{ //Example 5
std::unique_ptr<int> a(new int(5));
std::unique_ptr<int> b{new int(5)};
}
{ //Example 6
std::locale::global(std::locale("")); //copied from 22.4.8.3
std::locale::global(std::locale{""});
}
{ //Example 7
std::default_random_engine a {}; //Stroustrup's FAQ
std::default_random_engine b;
}
{ //Example 8
duration<long> a = 5; //Stroustrup's FAQ too
duration<long> b(5);
duration<long> c {5};
}
Pour chaque variable, je déclare, je pense que ce qui l'initialisation de la syntaxe à utiliser est et ce qui ralentit mon codage de la vitesse vers le bas. Je suis sûr que ce n'était pas l'intention d'introduire des accolades.
Quand il s'agit de modèle de code, la modification de la syntaxe peut conduire à des sens différents, donc nous allons la droit chemin est essentiel.
Je me demande si il y a un guide universel dont la syntaxe on doit choisir.
- Un exemple de comportement non voulu à partir de {} initialisation: string(50, 'x') vs string{50, 'x'} ici
Vous devez vous connecter pour publier un commentaire.
Je pense la suivante pourrait être une bonne ligne de conduite:
Si le (seul) la valeur que vous sont en cours d'initialisation est destiné à être le valeur exacte de l'objet, utiliser la copie (
=
) initialisation (parce qu'alors, en cas d'erreur, vous ne serez jamais accidentellement appeler explicitement le constructeur, qui interprète généralement la valeur fournie différemment). Dans les endroits où la copie de l'initialisation n'est pas disponible, voir si corset initialisation de la sémantique correcte, et si oui, utilisez-le, sinon utiliser des parenthèses d'initialisation (si ce n'est également pas disponible, vous êtes hors de la chance de toute façon).Si les valeurs sont en cours d'initialisation avec une liste de valeurs à stockées dans l'objet (comme les éléments d'un vecteur ou un tableau, ou réelle et partie imaginaire d'un nombre complexe), utiliser des accolades initialisation si disponible.
Si les valeurs sont en cours d'initialisation sont pas le stockage de valeurs, mais décrire la valeur/l'état de l'objet, utilisez des parenthèses. Des exemples sont la taille de l'argument d'un
vector
ou le nom de fichier en argument d'unefstream
.std::locale("")
?T {}
ou des raisons syntaxiques comme le plus délicate à analyser), mais en général, je pense que c'est un bon conseil. Notez que ceci est mon opinion subjective, donc on doit avoir un regard sur les autres réponses aussi.auto var = type(args);
type var{};
n'.auto var = type(args);
, et en montrant une syntaxe alternative qui serait à l'œuvre. En adhérant à des lignes directrices, même si il y a un facilement réparable faille est connue comme culte du cargo de programmation, et certainement pas quelque chose à approuver. Je n'ai pas downvote, et n'ont pas l'intention de disputer à ce sujet; vous devriez être content que quelqu'un est disposé à laisser des commentaires constructifs sur vos réponses, car il améliore la qualité de vos réponses.Je suis assez sûr il n'y aura jamais un guide universel. Mon approche est d'utiliser toujours des accolades de rappeler que
Si rond et accolades ne sont pas interchangeables. Mais savoir d'où ils diffèrent me permet d'utiliser bouclés plus ronde crochet d'initialisation dans la plupart des cas (certains des cas où je ne peux pas actuellement compilateur de bugs).
int i{0};
au lieu deint i=0;
en raison de la diminution de l'? Même Stroustrup ne pas aller aussi loin.int i = 0;
je ne pense pas que quiconque de l'utiliserint i{0}
là, et il pourrait être source de confusion (d'ailleurs,0
est si le typeint
, donc il n'y aurait pas de rétrécissement). Pour tout le reste, je suivrais Juancho conseils: préférez {}, méfiez-vous de les rares cas où vous ne devriez pas. Notez qu'il n'y a pas beaucoup de types qui vont prendre de l'initialiseur listes que les arguments du constructeur, vous pouvez vous attendre à conteneurs et de conteneurs tels que les types (tuple...) de les avoir, mais la plupart de code va appeler le constructeur approprié.int i{some floating point}
est une erreur, plutôt que d'en silence tronquer.{}
-syntaxe, je sais qu'il pourrait y avoir un rétrécissement; mais alors le compilateur ne veut pas me dire quelque chose de nouveau. Donc, soit je l'utilise toujours ou jamais.{}
pour dire "initialiser", sauf si vous avez absolument pas.entity{}
est toujours sûr à utiliser par défaut pour la construction; que si la classe n'a pas de constructeur par défaut serait un zéro-longueur de la liste d'initialiseur être utilisé (et seulement si il existe exactement une liste d'initialiseur constructeur).À l'extérieur de code générique (c'est à dire les modèles), vous pouvez (et je n') utiliser des accolades partout. Un avantage est qu'il fonctionne partout, par exemple, même pour l'initialisation de classe:
ou pour les arguments de la fonction:
Pour les variables, je ne paie pas beaucoup d'attention entre les
T t = { init };
ouT t { init };
styles, je trouve que la différence est mineure et, au pire, qu'une utile compilateur message à propos de l'utilisation abusive de l'explicit
constructeur.Pour les types qui acceptent
std::initializer_list
bien évidemment, parfois le non-std::initializer_list
constructeurs sont nécessaires (l'exemple classique étantstd::vector<int> twenty_answers(20, 42);
). C'est bien de ne pas utiliser des accolades, alors.Quand il s'agit de code générique (c'est à dire dans des modèles) que tout dernier paragraphe devrait avoir soulevé quelques mises en garde. Considérez les points suivants:
Puis
auto p = make_unique<std::vector<T>>(20, T {});
crée un vecteur de taille 2 siT
est par exempleint
, ou d'un vecteur de taille 20 siT
eststd::string
. Un très signe révélateur qu'il ya quelque chose de mal se passe ici est qu'il n'y a pas trait de caractère qui peut vous sauver ici (par exemple, avec SFINAE):std::is_constructible
est dans le plan de l'initialisation, alors que nous sommes en utilisant des accolades initialisation, qui reporte à l'direct-initialisation si et seulement si il n'y a pas de constructeur prenantstd::initializer_list
interférents. De mêmestd::is_convertible
est d'aucune aide.Je l'ai étudié si il est en fait possible de la main-roll un trait de caractère qui peut résoudre ça mais je ne suis pas trop optimiste à ce sujet. En tout cas, je ne pense pas que nous passerions à côté de beaucoup, je pense que le fait que
make_unique<T>(foo, bar)
résultat d'une construction équivalente àT(foo, bar)
est très intuitive, d'autant plus quemake_unique<T>({ foo, bar })
est tout à fait dissemblables et n'a de sens que sifoo
etbar
ont le même type.Donc génériques pour le code, je l'ai seulement utiliser des accolades pour une valeur d'initialisation (par exemple
T t {};
ouT t = {};
), ce qui est très pratique et je pense que supérieure à la C++03 façonT t = T();
. Sinon c'est direct syntaxe d'initialisation (c'est à direT t(a0, a1, a2);
), ou parfois par défaut de la construction (T t; stream >> t;
être le seul cas où j'utilise que je pense).Cela ne signifie pas que tous accolades sont si mauvais, considérons l'exemple précédent avec les corrections:
Ce toujours en utilisant des accolades pour la construction de la
std::unique_ptr<T>
, même si le type dépendent paramètre de modèleT
.make_unique<T>(20u, T {})
pourT
soitunsigned
oustd::string
. Pas trop sûr sur les détails. (Notez que j'ai aussi fait des commentaires sur les attentes concernant directement l'initialisation vs accolade de l'initialisation concernant, par exemple, parfaite-des fonctions de transfert.)std::string c("qux");
n'a pas été spécifiée pour travailler comme initialisation de classe pour éviter toute ambiguïté avec les déclarations de fonction dans la grammaire.