vector.push_back rvalue and copy-elision
Asked Answered
F

2

10

I push_back a temporary object into a vector like this,

vector<A> vec;
vec.push_back(A("abc"));

will the compiler apply copy-elision to construct the temporary A("abc") directly into the vector, so that A's copy ctor won't be triggered when pushing the temporary object into vec.

Fonteyn answered 9/8, 2012 at 2:25 Comment(3)
I don't think so because vector (STL allocators actually) uses placement new.Stomatitis
@Seth Carnegie - how does it relate to placement new? let's say you have enough free space in vector, then a compiler can just construct an instance of A in-place.Dzerzhinsk
@Nya because the compiler probably won't figure out where it will be created (not that it can't, but that it won't, because compiler writers didn't write that optimisation).Stomatitis
A
7

If you have a compiler that supports rvalue references, it will be moved into the vector, which is sometimes quite cheap.

An alternative to that is to directly construct the object in the vector, which can be done with vec.emplace_back("abc");. This only invokes one constructor.

Both of these are C++11 features. Copy elision is not allowed here, so without those features the copy will still be made.

However, if the copy constructor has no observable side-effects (which it shouldn't have anyway), a smart compiler may still perform that optimisation, because the "as-if" rule allows any optimisation that results in the same observable behaviour. I don't know if any current compiler does that, though. If not, I doubt anyone will spend the effort to add such an optimisation because rvalue references put an end to that need.

Amnesty answered 9/8, 2012 at 2:31 Comment(5)
@Fonteyn then a copy is likely to be made.Amnesty
@R.MartinhoFernandes or the assignment operator will be called; I've seen both cases occur, and I believe it depends on whether a copy constructor is defined or if an assignment operator is defined for the class (maybe both?). Another reason why "Effective STL" is a must-read for all C++ developers; Meyers talks about using classes with the STL containers, and touches on why/how to implement classes that will be stored within them.Warila
@Warila I don't see how the assignment operator can be called here: there is no existing object to assign to.Amnesty
@R.MartinhoFernandes actually, there is - in the vector. IIRC, and I was tinkering with this last night, it all depends if you have a copy constructor or not. If you have one, it is used to add the element to the vector. If not, and assuming you have a default constructor, a default instance is created and the object you are storing is assigned to it. Now, I'm working with an older gcc compiler, so maybe this has changed, but that was what I was seeing in my trace messages that I was emitting in each method call.Warila
@R.MartinhoFernandes Ok, tried something a little different - counting calls to each constructor. You're correct, the assignment op is not called because there is no constructed object. If you have a copy constructor, you'd never know what was happening -- removing it revealed what you said to be true. Never noticed this before, or just took for granted what was going on, so I just learned something new about a language that I've used for the better part of 20 years. I guess an old dog can learn new tricks :)Warila
A
2

In the general case, it cannot be done, it could potentially be done here as vector is a template and the code might be inlined, giving more information to the optimizer to do it's job and relieving some of the requirements of function calls.

In the general case, copy elision works by placing the two objects over the same location in memory and having just two names to refer to a single object. The problem in this case would be that one of the arguments must be located inside the vector (dynamically allocated, at a particular position), and the other is an argument to the function, which might be bound by the calling convention to a particular position in the stack. If that is the case, then the compiler will not be able to optimize the copy.

Africander answered 9/8, 2012 at 2:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.