3 ms·
I’m no C++ expert but couldn’t what emplace_back does not be achieved through compiler optimizations?
by addicted 2y ago
I’m no C++ expert but couldn’t what emplace_back does not be achieved through compiler optimizations?
- mattnewton 2y agoConstructors are just functions at the end of the day and they can do anything. Not really practical to decide when to invoke a constructor for the author in a language with semantics as complicated as C++. The convention there is to trust the author to be explicit with exactly where they want to point the gun and not try to move it from the author’s feet.
- binary132 2y agoNo, the signature of push_back accepts an object reference, while the signature of emplace_back accepts _arguments to forward to the element type’s constructor_. That means that pushback expects you to construct the object, while emplaceback wants to construct the object internally. It’s just that there’s usually a move constructor that accepts an object rvalue reference, so that case looks like it resembles the pushback API, if that makes sense....
- rocqua 2y agoThe additional copy used by push back can be observable (because the copy constructor is just a function, which is very much allowed to have side effects). That means the compiler isn't allowed to optimize out the copy.
- gpderetta 2y agoIn principle The Sufficiently Good compiler can do everything up-to the as-if rule. In practice most of the time the temporary object is optimized away. But if the object is very large or the copy has side effects, thing are harder or impossible and those are probably the times where you need the optimization the most.
- exitb 2y agoThe article makes it more complex than it needs to be. push_back and emplace_back have different goals. The former works with existing objects, the latter gets used when you intend to construct a new one, right in the collection. It happens to be that you can use emplace_back in place of push_back because copies and moves are just constructor overloads in C++. You shouldn't really use that, as it signals one intent, but does something else.
- binary132 2y agoYes, it’s confusing because of the semantic overlap between push accepting an object reference and _the vector element type’s constructor_ accepting an object reference.
- daemin 2y agoThe practical way I look at this is: In the vec.push_back(Widget(a, b, c)) case the Widget is constructed first, then it gets pushed to the container. At this point the container checks if it has enough storage and expands its storage if it needs to. Then the Widget is copied/moved into the containers storage. So the ordering would be: construct, check, resize, move/copy. While in the vec.emplace_back(a, b, c) case the container can check if it has space first before constructing the Widget directly inside the container. So the ordering would be: check, resize, construct. So you would need some exceptionally special circumstances for this conversion from the push case to the emplace case to occur.
- otabdeveloper4 2y agoNo, emplace_back is supposed to be a contract about non-copyable types. For trivially copyable types it is useless. The nuance is when types have complex or expensive rules for copying them. Here you want to be explicit about your intent w.r.t. copying.