2

It is my first time working with STL containers in C++ and while seeing different examples in Google I noticed something on the way vectors and sets are declared.

If you have a class A and you want to store such elements in a vector, you use a pointer to an A object (as shown below). While for sets, you use the actual object in the declaration. I was wondering if there is a particular reason for doing this, or it just happens in the examples I saw.

vector<*A> cont1;
set<A> cont2;
FranXh
  • 4,481
  • 20
  • 59
  • 78

7 Answers7

3

In most of cases, you'll end up using container of objects with automatic storage duration rather than pointers / smart pointers because such container will take care of the ugly memory management for you.

Simple std::vector<A> should suffice in most cases. Those are very rare situations that require to use std::vector<A*> instead. One example of such situation could be the need to achieve runtime polymorphism while using elements of this container. Another example might be using pointers due to performance issues that might appear when copying of A is expensive. Another reason can be avoiding of object slicing.

Good practice is to always use container of objects unless you have a really good reason to use container of pointers. And even if you need to hold pointers, then use smart pointers instead.

Related questions:
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?

Community
  • 1
  • 1
LihO
  • 41,190
  • 11
  • 99
  • 167
2

I'm not aware of this being common practice.

However, a possible reason for doing this is that as the vector resizes the contained objects can be moved in memory. If a contained object gives its this pointer to some other object, that pointer may be invalid after a resize. By storing pointers and managing the memory yourself, you objects wouldn't suffer from this.

With a set, you would not observe the same behaviour, as sets tend to be implemented as a tree. Beware though: I don't think the C++ Standard Library makes any guarantees about this...

If the authors are trying to exploit this with set then they are abusing the rules of encapsulation. If not, then the two examples you provided may be unrelated. There are many other reasons why you would store a pointer (or not) in a container, and you are free to choose.

paddy
  • 60,864
  • 6
  • 61
  • 103
  • 1
    The standard does guarantee that for `std::set`, references (and by extension, pointers) to elements are not invalidated by insert or erase operations, except of course references to an object being erased. – Benjamin Lindley Mar 06 '13 at 01:35
  • Thanks @BenjaminLindley for clarifying =) Hopefully most of the content of my answer is still useful! – paddy Mar 06 '13 at 01:39
  • Yes, of course it is still useful. In fact, I think it's the only one that actually highlights the reason you might use pointers in a vector that doesn't also apply to using poniters in a set. – Benjamin Lindley Mar 06 '13 at 01:46
1

It is just the examples you have encountered with. You can store anything from the object itself, to pointers, to function pointers in a vector. You can also store other vectors in a vector to define multi dimensional vectors:

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

vec[i][j] = a;     // write
int b = vec[i][j]; // read
meyumer
  • 5,063
  • 1
  • 17
  • 21
1
vector<A*> cont1;
cont1.push_back( new A( whatever ) );
vector<A> cont2;
cont2.push_back( A( whatever ) );

It depends which use-case you have. Do you want to store objects or pointers?

Note that the first example will need you to delete each object manually, whereas the second will handle deletion for you. Use the second wherever possible, unless you know what you're doing. It also makes assignment (etc.) safe.

Dave
  • 44,275
  • 12
  • 65
  • 105
1

It depends on what you want to store.

std::vector<A*> myVector;

...will create a vector that stores pointers to the A type.

std::set<A> mySet;

...will create a set that stores actual instances of the A type.

You could just as easily store actual instances in a vector:

std::vector<A> myVector;

Or pointers in a set:

std::set<A*> mySet;
chris-mv
  • 261
  • 2
  • 4
1

The real difference between sets and vectors is that a set contains all-unique elements, and has different runtimes for its operations. They aren't equivalent at all!

The reason for the difference is that you can have two dynamically-allocated objects that are equal, but stored in different locations. If you do this:

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

then myVector will contain two elements, but in the following case:

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

mySet will contain only one. This would not be the case had we used pointers.

Additionally, the reason (as others have noted) for dynamically allocating items for use in a vector is to reduce the overhead of an insertion.

Cheers!

Alex Reinking
  • 16,724
  • 5
  • 52
  • 86
1

Vectors are simple containers which can hold anything that's copyable. So, depending on your needs, you can put objects or pointers to objects in them.

While sets can also contain pointers, it usually does not make much sense to do so. Sets are ordered containers, which means that when you create a set, you need to specify a comparison function. If you don't specify one, a default comparison function (std::less<>) is used which depends on whatever you're storing in the set to have operator< defined. This will actually seem to work with pointers since you can compare pointers with <, but it compares the pointers and not the objects they point to, so the set will wind up being ordered by the relative location of the objects in memory.

Ferruccio
  • 98,941
  • 38
  • 226
  • 299