0

Every time you put object into std::vector it has to make a copy of that object.

So can I just put pointers instead of objects like that?:

Class *ptr_Class; Class object; ptr_Class = &object; std::vector<Class*> vector; vector.push_back(ptr_Class); 

Or for some reason it is not a good idea?

6
  • 1
    There is no problem putting pointers in vectors. It's quite common. The only thing you need to make sure of is that the objects are cleaned up correctly after use. I.e when the vector goes out of scope, and its destructor is called, it will not delete/free the objects (as opposed to putting copies in the vector, which does) Commented Jul 24, 2014 at 3:10
  • 1
    Copying problems are much less so in C++11. Commented Jul 24, 2014 at 3:15
  • "Every time you put object into std::vector it has to make a copy of that object." - not true; you can move objects into the vector, or you can construct objects directly in the vector. Commented Jul 24, 2014 at 3:15
  • Vectors of pointers is standard with basically any class (if you are at all concerned with performance). Like the other posters have mentioned, managing your memory is the difficult part. Commented Jul 24, 2014 at 3:15
  • 1
    @tpdietz, Vectors of pointers completely obliterate cache locality. They aren't a perfect solution. Anyway, there's also Boost's Ptr Containers, which are probably better than using a container of pointers. Commented Jul 24, 2014 at 3:17

3 Answers 3

3

Use a vector of smart pointers. in that way you will not get memory leaks.

The method you have described you have to be careful when popping from the list and you need to ensure that the list is empty when you have finished with it.

Sign up to request clarification or add additional context in comments.

Comments

1

You are not using "new", or allocating memory, so technically you won't have any memory leaks.

However, you have to be careful with scope. For instance, if you have

std::vector<Class*> funcFoo() { Class *ptr_Class; Class object; ptr_Class = &object; std::vector<Class*> vector; vector.push_back(ptr_Class); return vector; } 

you will end up with a vector of a pointer that pointed to an object in funcFoo. That object will likely be garbage after you leave the function.

I'm assuming that what you want is more like this:

Class *ptr_Class = new Class(); std::vector<Class*> vector; vector.push_back(ptr_Class); 

If this is the case, then you have to remember to deallocate any memory you allocated with new by calling delete.

For instance:

for (unsigned int i = 0; i < vector.size(); ++i) { delete vector[i]; vector[i] = NULL; } 

Comments

1

You can make a vector of pointers, but you have to be aware that the vector will not automatically call delete on the pointers when it's done with them. If your pointers were allocated with new, you have to delete them yourself before removing elements or destroying the vector, or you'll leak memory. It's tricky to make sure this cleanup happens in all cases; in particular, exceptions can cause cleanup code at the end of a function to be skipped.

It's safer to use a vector of smart pointers, which will take care of that cleanup automatically, even in the face of exceptions. In C++11 you can just make a vector of std::unique_ptr<T>. With older compilers that don't support C++11, you can use std::tr1::shared_ptr<T> or boost::shared_ptr<T> instead, though that has some overhead from reference-counting that you don't really need. You can't put C++98's std::auto_ptr in a vector (which is why it was deprecated and replaced with std::unique_ptr in C++11).

Also, in C++11 you have some options for avoiding the copy when inserting an object into a vector:

  • You can call myvector.push_back(std::move(myobject)) to move the object into the vector instead of copying it. This still constructs a new instance within the vector, but it's allowed to take ownership of any resources held by myobject instead of copying them. The myobject shouldn't be used afterward, since it no longer holds the data that it used to.
  • You can call myvector.emplace_back(...) to construct a new object directly into the vector's storage. This is basically a wrapper for your class's constructor, and can be given any set of arguments that are valid to pass to that constructor.

Note that if you want your vector to be polymorphic — that is, if you want to be able to store both squares and circles in a vector of shapes — then a storing pointers (preferably smart pointers) is your only option. All items actually stored within a vector must be the same type, so that type has to be something like a base-class pointer.

3 Comments

A vector of pointers isn't the only option for storing polymorphic objects. As Sean Parent demonstrated, you can make the polymorphism an implementation detail. The magic is at the bottom.
@chris, interesting idea there — basically a way to implement an "interface" with free functions instead of having to write a derived class by hand. But at the core it still works by holding a pointer to an abstract base class: concept_t in the video, DrawableConcept in your other link. All the rest is just to present a nicer API to the client.
Yeah, I really like it. In case you hadn't guessed, requiring member functions instead of free functions is trivial. I think that's what he does in the video.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.