Question

Depuis C ++ 11, les conteneurs de bibliothèque standard et std::string Demandez aux constructeurs de prendre une liste d'initialisateur. Ce constructeur a priorité sur d'autres constructeurs (même, comme l'a souligné @ JohannessChaub-Litb dans les commentaires, ignorant même d'autres critères de «meilleur match»). Cela conduit à quelques pièges bien connus lors de la conversion de tous () Formes de constructeurs à leurs versions contreventes {}

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>

void print(std::vector<int> const& v)
{
    std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ","));
    std::cout << "\n";
}

void print(std::string const& s)
{
    std::cout << s << "\n";
}

int main()
{
    // well-known 
    print(std::vector<int>{ 11, 22 });  // 11, 22, not 11 copies of 22
    print(std::vector<int>{ 11 });      // 11,     not 11 copies of 0

    // more surprising
    print(std::string{ 65, 'C' });      // AC,     not 65 copies of 'C'
}

Je n'ai pas trouvé le troisième exemple sur ce site, et la chose est apparue dans le salonu003CC++> Chat (en discussion avec @Rightfold, @abyx et @jerrycoffin), la chose quelque peu surprenante est que la conversion du std::string constructeur prenant un compte et un caractère à utiliser {} à la place de (), change sa signification de n copies du personnage au n-th caractère (généralement à partir de la table ASCII) suivi de l'autre caractère.

Ce n'est pas capturé par l'interdiction habituelle de l'auto à @JerryCoffin).

Question: Y a-t-il d'autres exemples qui se cachent dans la bibliothèque standard où la conversion d'un () Constructeur de style {} Style, est-il adapté avidement par un constructeur de liste d'initialisateur?

Était-ce utile?

La solution

Je suppose, avec vos exemples pour std::vector<int> et std::string Vous vouliez également couvrir les autres conteneurs, par exemple, std::list<int>, std::deque<int>, etc. qui ont le même problème, évidemment, comme std::vector<int>. De même, le int n'est pas le seul type car il s'applique également à char, short, long et leur unsigned Version (peut-être également quelques autres types intégraux).

Je pense qu'il y a aussi std::valarray<T> Mais je ne sais pas si T est autorisé à faire partie intégrante. En fait, je pense que ceux-ci ont une sémantique différente:

std::valarray<double>(0.0, 3);
std::valarray<double>{0.0, 3};

Il existe quelques autres modèles de classe C ++ standard qui prennent un std::initializer_list<T> Comme argument, mais je ne pense pas que l'un de ces éléments ait un constructeur surchargé qui serait utilisé lors de l'utilisation de parenthèses au lieu de bretelles.

Autres conseils

Juste à la recherche de l'occurrence de initializer_list.

  • Toutes les séquences, ce sont les constructeurs comme celui du vecteur:

    • se débarrasser
    • dynarray
    • avant-gardiste
    • liste
    • vecteur
  • Valarray

  • Basic_string

  • Collections non ordonnées, il y a un constructeur qui prend un entier pour déterminer le nombre initial du seau.

    • non ordonné_set
    • non ordonné_multiset

Je pense que c'est tout.

#include <unordered_set>
#include <iostream>

int main() {
    std::unordered_set<int> f (3);
    std::unordered_set<int> g {3};
    std::cout << f.size() << "/" << g.size() << std::endl; // prints 0/1.
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top