Undefined behavior with std :: move

From move page cppreference

Unless otherwise specified, all standard library objects that have been moved from them are placed in a valid but unspecified state. That is, only functions without preconditions, such as assigning an operator, can be safely used on an object after moving it from

So, from the example on the same page, this code below is considered undefined behavior

vector<string> v_string; string example = "example"; v_string.push_back(move(example)); cout << example << endl; 

MSVC will not output anything to the console, but if I do this

 vector<int> v_int; int number = 10; v_int.push_back(move(number)); cout << number << endl; 

Releases 10. Is there a reason why this happens? Or is it always undefined behavior?

+6
source share
3 answers

Unspecified does not mean undefined.

According to the C ++ 11 standard, section 17.3.26:

actual, but undefined state state of the object that is not specified, except that the invariants of the objects are satisfied, and operations on the object behave as indicated for its type

Since the object is in a valid state, you can pass it to the output because streaming does not have additional prerequisites. However, what is printed is not indicated, so it may simply not print or print that your father smells like elderberry. What you cannot safely do is use a function with additional preconditions such as back() , which additionally requires the line to be nonempty. Valid lines may be empty.

Containing the old value is a perfectly acceptable option for an unspecified but valid state. In the case of fundamental types such as int , a simple copy is just the most efficient way to perform the move.

It should also be noted that int not a standard library object, but a fundamental type (as defined in section 3.9.1). Therefore, your quote does not apply.

+10
source

This is because string can effectively move d due to theft of a pointer pointing to the actual characters, so that is what compilers do, leaving move d from string "empty". int cannot be effectively move d, you are just making a copy. Therefore, the old int still exists. But this is not so. Just don't use the objects you move ed, and don't rely on unspecified behavior.

+3
source

Undefined behavior just means

for which this International Standard does not impose any requirements. Acceptable undefined behavior varies from ignoring the situation completely with unpredictable results, behaving during the translation or execution of the program in a documented manner specific to (with or without a diagnostic message), to stop the translation or execution (with issuing a diagnostic message). Many erroneous software constructs do not generate undefined behavior; they must be diagnosed.

If you're interested, see What Every C Programmer Should Know About Undefined Behavior . It is truly eye-opening.

In your case, this is not undefined behavior, but an unspecified state: In 21.4.2.16, the C ++ standard defines the semantics of the move constructor:

Creates an object of class basic_string, as shown in table 69. The saved allocator is built from alloc. In the second form, str remains in a valid state with an undefined value.

The "second form" is a move constructor, so the string is in an undefined state.

This means that the object must be in a state in which the invariants meet, but nothing else is indicated. For the string, any content will be fine.

0
source

All Articles