How many copies happen/object exist in the following, assuming that normal compiler optimizations are enabled:
std::vector<MyClass> v;
v.push_back(MyClass());
If it is not exactly 1 object creation and 0 copying, What can I do (including changes in MyClass) to achieve that, since it seems to me that that is all that should really be necessary?
If the constructor of
MyClasshas side-effects, then in C++03 the copy is not permitted to be elided. That’s because the temporary object that’s the source of the copy has been bound to a reference (the parameter ofpush_back).If the copy constructor of
MyClasshas no side-effects then the compiler is permitted to optimize it away under the “as-if” rule. I think the only sensible way to determine whether it actually has done so with “normal optimizations” is to inspect the emitted code. Different people have different ideas what’s normal, and a given compiler might be sensitive to the details ofMyClass. My guess is that what this amounts to is whether or not the compiler (or linker) inlines everything in sight. If it does then it will probably optimize, if it doesn’t then it won’t. So even the size of the constructor code might be relevant, never mind what it does.So I think the main thing you can do is to ensure that both the default and the copy constructor of
MyClasshave no side-effects and are available to be inlined. If they’re not available then of course the compiler will assume that they could have side-effects and will do the copy. If link-time optimization is a normal compiler option for you, then you don’t have to do much to make them available. Otherwise, if they’re user-defined then do it in the header file that definesMyClass. You might be able to get away with the default constructor having certain kinds of side-effects: if the effects don’t depend on the address of the temporary being different from the address of the vector element then “as-if” still applies.In C++11 you have a move (that likewise must not be elided if it has side-effects), but you can use
v.emplace_back()to avoid that. The move would call the move constructor ofMyClassif it has one, otherwise the copy constructor, and everything I say above about “as-if” applies to moves.emplace_back()calls the no-args constructor to construct the vector element (or if you pass arguments toemplace_backthen whatever constructor matches those args), which I think is exactly what you want.