Question

Pourquoi est-ce que le constructeur de paramètre unique de std::list<T> nécessite T être un type par défaut constructible? Je veux dire le code suivant ne compile pas.

struct Foo { // does not have default constructor.
  Foo (int i) {} 
}
int main(void) {
  std::list<Foo> l(10);
}

Il semble possible d'utiliser le construire et détruire idiomes comme ils l'ont déjà fait dans le std :: vecteur, mais avec plus de maintien de la classe livre de liste.

Sur le même sujet, pourquoi ne pas avoir la fonction de la capacité dans la liste? Vous pouvez faire valoir qu'une telle fonction payer le coût de l'allocation de mémoire à l'avance et éliminer les frais généraux plus tard que vous push_back objets. Au moins, il fera les interfaces de deux conteneurs de séquence STL légèrement plus cohérente.

Était-ce utile?

La solution

std :: liste n'a pas de fonction de la capacité, car il n'a pas de sens; il ne doit jamais redimensionner comme un vecteur fait. Sa capacité est limitée que par la mémoire disponible, ce qui est difficile à déterminer.

D'après ce que vous avez demandé, je pense que vous voulez réellement réserve (). C'est unique pour le vecteur parce qu'il (mal) a besoin d'une telle chose; il n'y a pas d'exigence particulière de faire toutes les fonctions cohérentes dans tous les conteneurs STL, surtout quand ils ont peu de sens pour les autres.

Vous pouvez obtenir le même effet en utilisant un allocateur personnalisé. Comme Manuel suggéré, regardez coup de fouet.

Autres conseils

Il n'y a pas d'exigence générale que le type soit par défaut constructible - il doit être copiable et cessible. Votre code ne fonctionne pas parce que vous essayez de créer une liste de 10 articles - ils doivent être construits en quelque sorte et ainsi le constructeur par défaut doit être utilisé - mais seulement dans ce cas précis. Si vous avez créé une liste vide et ajouté, il n'y aurait pas une telle exigence.

La même chose est vrai pour d'autres conteneurs - essayez de compiler les éléments suivants:

#include <vector>

struct A {
    A( int x ) : z(x) {}
    int z;
};

std::vector <A> a(10);

En ce qui concerne la deuxième partie de votre question, je voudrais simplement observer que la cohérence de l'interface n'a pas été un critère de conception de choix pour les conteneurs standard - il n'y a pas l'intention, par exemple, qu'un type de conteneur est un « drop-in "remplacement d'un autre. Il y a une bonne discussion sur cela dans les articles 1 et 2 du livre de Scott Meyers « STL efficace ».

Neil a déjà répondu à la principale question.

Notez également que vous avez besoin d'un constructeur par défaut lorsque vous appelez redimensionner ().

Vous pouvez contourner cela en ayant une liste STL de pointeurs vers des objets, mais je suppose que cela était déjà évident pour vous.

  

Sur le même sujet, pourquoi ne pas avoir la   fonction de la capacité dans la liste? Vous pouvez   soutiennent qu'une telle fonction payerait   coût d'allocation de mémoire à l'avance et   éliminer les frais généraux plus tard que vous   objets push_back. Au moins il sera   rendre les interfaces de deux STL   récipients en séquence un peu plus   cohérente.

Je suppose que le problème est que listes STL permettent épissage liste croix . Si vous voulez allouer de la mémoire dès le départ, un coup d'oeil à la Boost Piscine Allocataire .

La raison en est que, quand on construit une liste de n éléments (n étant le paramètre utilisé dans le constructeur), la liste remplit sa structure de n éléments avec des copies de T ().

Voir sgi documentation stl pour la liste .

  

Pourquoi est-ce que le seul paramètre   constructeur de std :: liste nécessite T   être un type par défaut constructible?

Parce que ce contructor - crée la liste des éléments (numéro que vous passez comme paramètre). Valeur de chaque élément sera par défaut. vous pouvez également utiliser constructeur avec deux paramètres, pour créer la liste des éléments qui seront initialisées avec la deuxième valeur de l'élément.

  

Sur le même sujet, pourquoi ne pas avoir la   fonction de la capacité dans la liste?

Il n'a pas de sens, parce que le coût de l'ajout de nouveaux éléments à la liste est beaucoup plus faible que dans le cas avec le vecteur.

  

std :: vecteur n'a pas un tel   restriction. Ma question est pourquoi ne pas   utiliser les mêmes techniques   (Création / destruction des idiomes) dans la   std :: liste aussi bien?

Il n'est pas restriction. Parce que si vous n'utilisez pas de constructeur, initialiseur par défaut ne sera pas nécessaire. Même chose pour vrai vecteur.

Votre question est vraiment « pourquoi ne pas avoir des fonctions de réserve et de capacité dans la liste? »

La réponse est qu'il n'y a aucune raison de réserver de la mémoire à l'avance pour la liste - l'ajout de nouveaux éléments nécessite jamais un realloc et copier des éléments existants, il n'y a pas d'exigence que la mémoire contenant le contenu d'une liste soit contiguë, et itérateurs ne soyez pas invalidée lorsque vous faites un list::push_back().

Tous ces éléments sont la raison de l'existence de vector<>::reserve(), et ayant la mémoire en réserve pour les nouveaux éléments est pourquoi un vector<> effectuera new de placement en mémoire brute.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top