2013-03-06 5 views
2

Il est la première fois travailler avec des conteneurs STL en C++ et en voyant différents exemples dans Google je remarquai quelque chose sur les vecteurs de façon et ensembles sont déclarés.Déclarant vecteurs et ensembles en C++

Si vous avez une classe A et que vous voulez stocker ces éléments dans un vecteur, vous utilisez un pointeur vers un objet A (comme illustré ci-dessous). Alors que pour les ensembles, vous utilisez l'objet réel dans la déclaration. Je me demandais s'il y a une raison particulière pour ce faire, ou il se trouve dans les exemples que j'ai vu.

vector<*A> cont1; 
set<A> cont2; 

Répondre

1

Les vecteurs sont de simples conteneurs pouvant contenir tout ce qui peut être copié. Ainsi, en fonction de vos besoins, vous pouvez placer des objets ou des pointeurs sur des objets qui s'y trouvent.

Alors que les ensembles peuvent également contenir des pointeurs, cela n'a généralement pas beaucoup de sens. Les ensembles sont des conteneurs ordonnés, ce qui signifie que lorsque vous créez un ensemble, vous devez spécifier une fonction de comparaison. Si vous n'en spécifiez pas, une fonction de comparaison par défaut (std::less<>) est utilisée. Elle dépend de ce que vous stockez dans l'ensemble pour que operator< soit défini. Cela semble fonctionner avec les pointeurs puisque vous pouvez comparer les pointeurs avec <, mais compare les pointeurs et pas les objets qu'ils pointent, de sorte que l'ensemble sera ordonné par l'emplacement relatif des objets en mémoire.

1

Ce sont juste les exemples que vous avez rencontrés. Vous pouvez stocker n'importe quoi de l'objet lui-même, aux pointeurs, aux pointeurs de fonction dans un vecteur. Vous pouvez également stocker d'autres vecteurs dans un vecteur pour définir des vecteurs multidimensionnels:

// define 4x4 vector 
vector< vector<int> > vec(4, vector<int>(4)); 

vec[i][j] = a;  // write 
int b = vec[i][j]; // read 
1
vector<A*> cont1; 
cont1.push_back(new A(whatever)); 
vector<A> cont2; 
cont2.push_back(A(whatever)); 

Cela dépend du cas d'utilisation que vous avez. Voulez-vous stocker des objets ou des pointeurs?

Notez que le premier exemple devra vous delete chaque objet manuellement, tandis que la seconde traitera la suppression pour vous. Utilisez le second autant que possible, sauf si vous savez ce que vous faites. Il rend également la tâche (etc.) sûre.

1

Cela dépend de ce que vous voulez stocker.

std::vector<A*> myVector; 

... va créer un vecteur qui stocke les pointeurs vers le type A.

std::set<A> mySet; 

... crée un ensemble qui stocke les instances réelles du type A.

Vous pouvez simplement stocker facilement des cas réels dans un vecteur:

std::vector<A> myVector; 

ou des pointeurs dans un ensemble:

std::set<A*> mySet; 
2

Je ne suis pas au courant de ce qui est pratique courante.

Cependant, une raison possible de le faire est que le vector redimensionne les objets contenus peuvent être déplacés dans la mémoire. Si un objet contenu donne son pointeur this à un autre objet, ce pointeur peut être invalide après une resize. En stockant des pointeurs et la gestion de la mémoire vous-même, vous ne souffrirait pas des objets de cette situation.

Avec un set, vous ne respecterait pas le même comportement, comme des ensembles ont tendance à être mis en œuvre comme un arbre. Attention cependant: je ne pense pas que la bibliothèque standard de C++ donne des garanties à ce sujet ...

Si les auteurs essayent d'exploiter ceci avec set alors ils abusent des règles d'encapsulation. Si non, alors les deux exemples que vous avez fournis peuvent ne pas être liés. Il y a beaucoup d'autres raisons pour lesquelles vous stocker un pointeur (ou non) dans un récipient, et vous êtes libre de choisir.

+1

La norme garantit que pour 'std :: set', les références (et par extension, les pointeurs) aux éléments ne sont pas invalidées par les opérations d'insertion ou d'effacement, sauf bien sûr les références à un objet en cours d'effacement. –

+0

Merci @BenjaminLindley pour clarifier =) J'espère que la plupart du contenu de ma réponse est toujours utile! – paddy

+0

Oui, bien sûr, c'est encore utile.En fait, je pense que c'est le seul qui met en évidence la raison pour laquelle vous pourriez utiliser des pointeurs dans un vecteur qui ne s'applique pas à l'utilisation de poniters dans un ensemble. –

3

Dans la plupart des cas, vous finirez par utiliser conteneur d'objets ayant une durée de stockage automatique plutôt que des pointeurs/pointeurs intelligents parce que ce récipient se chargera de la gestion de la mémoire laide pour vous.

Simple std::vector<A> devrait suffire dans la plupart des cas. Ce sont des situations très rares qui nécessitent d'utiliser std::vector<A*> à la place. Un exemple d'une telle situation pourrait être la nécessité d'atteindre polymorphisme d'exécution tout en utilisant des éléments de ce conteneur. Un autre exemple pourrait être l'utilisation de pointeurs en raison de performances problèmes qui peuvent apparaître lorsque la copie de A est coûteux. Une autre raison peut être d'éviter tranchage d'objet.

Une bonne pratique consiste à toujours utiliser le conteneur d'objets, sauf si vous avez une très bonne raison d'utiliser un conteneur de pointeurs. Et même si vous devez conserver des pointeurs, utilisez plutôt les pointeurs intelligents à la place.

questions connexes:
How to avoid memory leaks when using a vector of pointers to dynamically allocated objects in C++?
C++: Vector of objects vs. vector of pointers to new objects?

1

La vraie différence entre les jeux et vecteurs est qu'un ensemble contient des éléments uniques tout, et a des runtimes pour ses opérations. Ils ne sont pas du tout équivalents!

La raison de la différence est que vous pouvez avoir deux objets alloués dynamiquement qui sont égaux, mais stockés dans des emplacements différents. Si vous faites ceci:

A a,b; 
std::vector<A> myVector; 
myVector.push_back(a); 
myVector.push_back(b); 

alors myVector contiendra deux éléments, mais dans le cas suivant:

A a,b; 
std::set<A> mySet; 
mySet.insert(a); 
mySet.insert(b); 

mySet ne contiendra qu'un seul. Ce ne serait pas le cas si nous avions utilisé des pointeurs.

De plus, la raison (comme d'autres l'ont noté) pour l'allocation dynamique d'éléments à utiliser dans un vecteur est de réduire le temps système d'une insertion.

À la votre!