Reputation: 1181
From the move page of the cppreference
Unless otherwise specified, all standard library objects that have been moved from are placed in a valid but unspecified state. That is, only the functions without preconditions, such as the assignment operator, can be safely used on the object after it was moved from
So, from the example on the same page, this code below is considered undefined behaviour
vector<string> v_string;
string example = "example";
v_string.push_back(move(example));
cout << example << endl;
MSVC will output nothing on the console, but if I do this
vector<int> v_int;
int number = 10;
v_int.push_back(move(number));
cout << number << endl;
will output 10. Is there a reason why this happens? Or is it always undefined behavior?
Upvotes: 9
Views: 2629
Reputation: 9991
That is because a string
can be efficiently move
d from by stealing the pointer that points to the actual characters, so thats what compilers do, leaving the move
d from string
"empty". An int
cannot be efficiently move
d, you just make a copy. Therefore the old int
is still there. But that is off the record. Just do not use objects that you move
ed from and don't rely on unspecified behavior.
Upvotes: 3
Reputation: 6757
Unspecified does not mean undefined.
According to the C++11 standard, section 17.3.26:
valid but unspecified state an object state that is not specified except that the object’s invariants are met and operations on the object behave as specified for its type
As the object is in a valid state, you can stream it to an output, as streaming has no additional preconditions. However what is printed is unspecified, so it may just print nothing, or print that your father smells of elderberries. What you can not safely do is use a function with additional preconditions such as back()
which additionally requires the string to be non-empty. Valid strings can be empty.
Containing the old value is a perfectly acceptable option for the unspecified but valid state. In case of fundamental types such as int
a simple copy is just the most efficient way to perform a move.
It should also be noted that int
is not a standard library object, but a fundamental type (as defined in section 3.9.1). Therefore your quote does not apply.
Upvotes: 13
Reputation: 9406
Undefined behavior just means
behavior for which this International Standard imposes no requirements. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed.
If you are interested, take a look at "What every C programmer should know about undefined behavior". It is really an eye-opener.
In your case, it is not undefined behavior but unspecified state: In 21.4.2.16, the C++ standard defines the move constructor's semantics:
Constructs an object of class basic_string as indicated in Table 69. The stored allocator is constructed from alloc. In the second form, str is left in a valid state with an unspecified value.
The "second form" is the move constructor, so the string is in an unspecified state.
That means that the object must be in a state that invariants are met, but anything else is unspecified. For a string, any content would be ok.
Upvotes: 0