简体   繁体   中英

C++: What to insert in vectors - pointers or references, when does a vector copy it's elements?

Suppose I have complex objects, like structs containing a huge amount of members - and I want to store them in a vector.

Now vector::push_back(...) works over call-by-reference (rather than call-by-value), so in the first moment the passed object is not copied. But what about later? Does a vector internally store pointers or direct references? When the vector needs to expand, are the contained elements themselves copied or their addresses?

This finally results in the question, if - for large objects - the objects themselves should be stored in a vector or rather pointers to these objects. Is there a kind of best practice for that?

vector::push_back(...) works over call-by-reference (rather than call-by-value), so in the first moment the passed object is not copied

vector::push_back() stores the copy of the object being added to it.

Does a vector internally store pointers or direct references?

How a vector internally stores elements is an implementation detail but the complexity and the behavior requirements leave little room for variation. Vector stores the elements in a contiguous memory locations much like arrays.

When the vector needs to expand, are the contained elements themselves copied or their addresses?

When a vector expands, it needs to copy all the objects to a new contiguous memory, again this is a implementation detail. If elements are pointers then the pointers themselves will be copied.

The objects themselves should be stored in a vector or rather pointers to these objects. Is there a kind of best practice for that?

If your objects are bigger and you do not want to place them in a vector then you can store pointers to them in the vector but then do not store raw pointers in vector, use a suitable smart pointer as per your requirement. It ensures perfect RAII and you do not need to be bothered about the memory management explcitily.

std::vector::push_back saves copy of the object.

If you need performance by avoiding copy, then you could use vector of pointers.

std::vector<BigObject*> objects; //manage memory yourself

Or you can use some sort of smart pointer, so as to avoid managing memory yourself. For example, you could use std::unique_ptr if your compiler supports it:

std::vector<std::unique_ptr<BigObject>> objects;

If you use pointers (or smart pointers), then copying is still there, but this time, the copy is done for pointers (or smart pointers) which is much cheaper.

From @Loki's comment:

Or you can use boost::ptr_vector<> which is designed to hold pointers and will return references when accesses thus makeing it easy to use standard algorithms as they all expect objects.

Actually, if you're iterating over the vector more than you're adding objects to it, you will greatly outperform pointer by adding objects, as they will be contiguous in memory.

However if you're doing more adding and erasing to and from the vector, than you are iterating over it, pointers will be more efficient.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM