Probably, a lame question, but I keep failing to find comprehensive answer.
Parameters of std::vector::emplace_back
are r-value references. As far as I understand, it is unsafe to use object after it was passed somewhere by r-value reference. I mean following:
std::string str("hello world");
std::string str2(std::move(str)); // string::string(string &&);
cout << str; // unsafe, str was moved to str2
So, what will happen in following example?
std::vector<std::string> array;
std::string str("hello world"); // what if add 'const' qualifier here?
array.emplace_back(str); // template <class... Args>
// void emplace_back (Args&&... args);
std::cout << str; // safe or not? str was moved or copied?
I'm really confused here. My tests shows that,str
is safe to use after emplace_back
, but my (broken?) logic tells me that str
was moved and shouldn't be used after that.
PS. Sorry for my bad English :)
The parameters for emplace
-style functions are forwarding references, which means they become lvalue references for lvalue arguments and rvalue references for rvalue arguments.
With
array.emplace_back(str);
str
is an lvalue (you have not cast it to an rvalue with std::move
) so it will be copied. It will retain its value after the call.
A standard library object will generally be in a "valid but unspecified state".
valid but unspecified state
a value of an object that is not specified except that the object’s invariants are met and operations on the object behave as specified for its type [Example: If an object x of typestd::vector<int>
is in a valid but unspecified state,x.empty()
can be called unconditionally, andx.front()
can be called only ifx.empty()
returnsfalse
. —end example]
Most often this means either empty, or retaining the original value. Moving an int
probably doesn't reset its value.
Some types are more specified, for example unique_ptr
always holds a nullptr after being moved from.
So, in this case
std::string str("hello world");
std::string str2(std::move(str)); // string::string(string &&);
cout << str;
the code is valid, but we don't know exactly what the output will be, if any. Makes it less than useful.
The idea is that you should let the variable go out of scope after being moved from, or assign it a new value to use it further.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With