Which C++ object copies more quickly? - c++

Two instances of this C++ object exist.
my_type
{
public:
std::vector<unsigned short> a;
}
One where the std::vector is empty and the other where it contains 50 elements.
Which instance copies most quickly or do they copy in the same time?

When a std::vector is copied all of it's elements are also copied - so the time taken should be proportional to vector.size().
In c++0x so called move semantics are introduced, allowing a move constructor and move assignment operator to be defined for types. These are defined for standard library containers (such as std::vector) and should allow for vector's to be moved in O(1) time. If you're worried about performance, maybe you could re-cast your operations to make use of these new features.
EDIT: Based on the linked question, if you're worried about the extra copies potentially done when calling vector::push_back you have a few options:
In c++0x use the new vector::emplace_back instead. This allows for your objects to be constructed in-place in the container.
In c++0x use move semantics, via something like vector.push_back(std::move(object_to_push)). For POD types this will still do more copying than the emplace_back option.
Store a container of pointers to objects rather than objects themselves. The only thing that will get copied by the container in this case is the pointer itself - which is cheap. You potentially want to use some variant of smart pointers with this option.
Hope this helps.

Related

Are there any performance differences between std::copy and the container's copy constructor?

std::copy is a more general approach since it can handle containers with differing value types (e.g. copy from std::vector<float> to std::vector::<double>). But when the value type is the same for both containers, does it matter whether I use the copy constructor instead of std::copy?
Don't worry about performance, they should all be super close. Instead:
If you're creating a new container that's a copy, use the copy constructor or two-iterator constructor (if different element types).
If you're replacing (assigning) an existing container, use the appropriate assignment operator or assign member.
If you're replacing a subset of elements, use std::copy.
By accurately representing what you're trying to do, you give the compiler the most possible information to optimize its code (for example constructing directly from an existing container it can pre-allocate exactly the right about of memory).
One potentially important difference is when you have a situation where you are able to invoke the move constructor rather than the copy constructor (e.g. when the object you are copy constructing from is an rvalue, such as the return value of a function). If you have such a situation, you definitely want to make sure you take advantage of it by move constructing or move assigning rather than using std::copy.
Basically this is just another reason to follow Mark B's advice.

C++ Containers and right hand side

I've read today that you should not use the STL containers for auto_ptr because of
the fact that the auto_ptr deletes it rhs value in the = operator.
So i have 2 question :
1) Does this mean that all classes that have this behavior should not be used in containers?
2) what sort of containers can you use?
1) Does this mean that all classes that have this behavior should not
be used in containers?
Yes indeed, because that is not correct copying behaviour, since the copy is not equal to the source afterwards but destroys the source. This is kind of a broken implementation of move-semantics before C++11, required for the strict unique ownership semantics of std::auto_ptr.
2) what sort of containers can you use?
The real answer is actually, that classes having this behaviour (a copy constructor/assignment destroying its source) should just not exist. And fortunately this is not needed anymore nowadays, since C++11 has proper move-semantics, which realize exactly this destructive copy but in a safe way (simply said, only when the source is really not needed anymore).
Therefore std::auto_ptr is deprecated and should not be used anymore. It has been replaced by std::unique_ptr which is movable but not copyable. But since C++11 containers rather move their elements than copy when appropriate, a std::unique_ptr can be used perfectly inside of standard containers. You just cannot copy the container or fill it with a single object which would require copies of std::unique_ptrs, but those operations should not work anyway, since they are conceptually wrong for unique ownership semantics.
And as a side note, if you actually chose std:auto_ptr for a reason, that is you want unique ownership semantics, then a std::shared_ptr (as suggested by other answers) is plain wrong since it exhibits shared ownership. std::unique_ptr is today's std::auto_ptr. Never spam std::shared_ptrs where std::unique_ptrs (or even raw pointers, but from your question I rule that option out) are appropriate.
Auto pointer has a very strict ownership: it and only it is responsible for the lifetime of the object it points at. If you copy an auto_ptr, you lose the reference to what it pointed at.
The problem is in the way STL containers do their stuff. For example, when you are adding an element, the container might expand to get more memory, which leads to copying all the values to the new memory, which, itself, leads to losing the auto_ptrs.
I think that associative containers might not copy themselves entirely when they allocate additional memory, but I'm absolutely not sure, if someone can confirm it, please post a comment, or just edit my answer. Anyway, you'd better not risk it.
Also note that Auto_ptr is deprecated since C++0x, it is advised to use unique_ptr instead. In your case, std::shared_ptr will probably do the trick, unless you really need unique ownership for those objects of yours.
Exactly.
In general, sequence container elements must be CopyConstructible and Assignable. This means that they require:
public copy constructor
public assignment operator
Asociative containers (set<> and map<>) also must provide strict weak ordering, i.e. operator < must be defined (or a dedicated comparison function).
Chapter 23.1 of C++ standard provides detailed requirements.

c++ vector with strict ownership semantics

This is not a question about putting std::auto_ptr into std::vector.
Is there some vector equivalent of std::auto_ptr in std::, std::tr1:: or boost::? I use std::auto_ptr in function parameters and return values to decalre ownership semantics of these functions. But this way I can pass only single objects. As a temporary solution for vectors I have this:
std::auto_ptr<std::vector<std::tr1::shared_ptr<ClassExample> > > fx(....);
which, I suppose, by introducing boost, I will be able to change into this:
std::auto_ptr<std::vectro<boost::unique_ptr<ClassExample> > >f(...);
in order to define strict ownership passing, but it seems to be quite complicated. To simplify it, I can use
std::vector<boost::unique_ptr<ClassExample> > f(...);
as the price for deep copy of the vector is not high, but I am still curious if there is something that I can use like this:
auto_vector<ClassExample> f(...);
meaning that the function is releasing ownership of all the objects and the vector internal data array is not deeply copied.
There's a C++11 solution - it requires an implementation that provides r-value references and has a standard library updated to include move constructors and std::unique_ptr.
Just return std::vector<std::unique_ptr<T>> - that type can't be copied, as std::unique_ptr<T> isn't copyable. The compiler will either use the move constructor when returning, which will not invoke a deep copy or will apply the RVO and elide the construction of a new object.
Without any particular reason as to why you need to maintain a vector of pointers, the first solution would be to ditch all the complexity and go for the simple:
std::vector<Type> f();
Ownership of the objects is unique (the vector owns them), and while the code looks like it is copying the vector on return it will be optimized away in most cases.
If you need the objects inside the vector to be dynamically allocated due to some other requirement (objects must be allocated through a factory, they are pointers to derived types, or they cannot move due to vector growth -- code maintains references/pointers) that you are not showing then I would go for a boost::ptr_vector that will maintain ownership of the contained objects. Again, return by value:
boost::ptr_vector<Type> f();

custom allocator using move for vector of thread

I'm currently learning about concurrency in C++ and came across using a vector of threads, which I believe will be possible in C++0x. However, my current compiler doesn't appear to have an implementation of move-aware containers and so I get errors generated because std::thread::thread(const std::thread&) is deleted, ie I can only use the move constructor/move assignment with std::thread.
Am I correct in thinking I could circumvent this issue by writing a custom allocator using
void MyAllocator::construct (pointer p, reference val)
/* should be non-const reference to val because using move constructor? */
{
new ((void*)p) T (std::move(val));
}
rather than
void allocator::construct (pointer p, const_reference val)
{
new ((void*)p) T (val);
}
? Or some other variation on this theme (possibly using an overload of MyAllocator::construct).
NB: This is mainly intended to be a short-term educational exercise and well enough performing work around to play around with threads in containers. I'd only be using MyAllocator in this context. However, please also point me at any libraries that may have this implemented so I can have a poke around the source.
If your compiler doesn't provide a move-aware std::vector then you'll have to write your own specialization of std::vector<std::thread> rather than just provide a custom allocator. The whole C++03 vector interface relies on copying: push_back() copies elements in; resize() initializes the empty elements with a copy of the element passed as the second parameter (even if that is the default value of T()); resize(), reserve(), insert(), erase() and push_back() will copy elements if the vector needs reallocating, or elements otherwise need moving around, and so forth.
This is such a common problem that I've included such a specialization with my (commercial) just::thread implementation of std::thread.
The easiest way to circumvent the problem would be to allocate the threads on the heap and manipulate pointers to them.
Check the Boost Pointer Container library: boost::ptr_vector<std::thread> seems to me what you are looking for.
The requirement that std containers only take copyable objects has more to do with the C++03 container interfaces than it does with the allocator implementation.
For example
vector<T> b(100);
vector<T> a;
a=b;
assert(a==b);
The standard assures us a==b is true. However, if T were not copyable, then in the best case a=b will not compile, in the worst a=b is undefined. Furthermore,
a.push_back(T());
may cause a to allocate new space, and under the hood there are copies made to the new underlying storage from the old.
Furthermore, there is nothing in the C++03 standard that says an implementation actually has to call allocator.construct, and in fact many (gcc for example) do not.
The C++0x standard adds new member functions to the container interface for moveable types, and clarifies how things like operator= behave in their presence.
See www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2486.pdf

RAII and C++ STL

I have a case where I wish to store a list of resources in a std::vector. As I see it, my options are as follows:
Give my resource a default constructor
Store them as heap objects (and wrap them in a shared pointer)
Option 1 makes it possible to construct invalid resources and option 2 forces me to use the heap.
Am I missing any options here?
You don't need a default constructor to have a vector of instances.
The only limitation is you can't use vector::resize with the default argument when the class has no default constructor.
vec.resize(20); // requires default constructor
but you can give vector::resize a default object:
std::vector<foo> vec;
vec.resize(20, foo(10)); // give a sample object since foo has not default constructor
You may store objects with non trivial constuctor in vector. The the objects store in stl containers should have assignment semantic (copy constructor and assign operator).
A third option would be to use Boost.PointerContainer. However, your objects will still be individually allocated on the heap. As Johann has commented, std::vector already makes use of the heap to store objects (contiguously), so there's no way to completely avoid the heap.
It often doesn't make sense to allow resources (such as mutexes, I/O streams, etc) to have copy semantics. So they must be rendered non-copyable by making the copy constructor and assignment operator private. Unfortunately, the non-copyable restriction makes it impossible to store resources directly as values inside STL containers. One must therefore resort to either Boost.PointerContainer or containers of smart pointers. The Motivation section of the Boost.PointerContainer documentation explains why you'd prefer to use one over the other.