Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: minor editorial changes

...

Passing an object as a function argument that binds to an rvalue reference parameter, including via implicit function call syntax such as move assignment or move construction, moves the object's state into another object. Upon return from such a function call, the object which that was bound as an rvalue reference parameter is considered to be in the moved-from state. Once an object is in the moved-from state, the only operations that may be safely performed on that object instance are ones for which the operation has no preconditions, because it is unknown whether the unspecified state of the object will satisfy those preconditions. While some types have explicitly-defined preconditions, such as types defined by the Standard Template Library, it should be assumed that the only operations that may be safely performed on a moved-from object instance are reinitialization through assignment into the object , or terminating the lifetime of the object by invoking its destructor.

...

The following Standard Template Library functions are guaranteed to leave the moved-from object in a well-specified state:.

TypeFunctionalityMoved-from State
std::unique_ptrMove construction, Move assignment,
"Converting" move construction, "Converting" move assignment
(Likewise for std::unique_ptr for array objects with a runtime length)
The moved-from object is guaranteed to refer to a null pointer value, per [unique.ptr], paragraph 4 [ISO/IEC 14882-2014].
std::shared_ptr

Move construction, Move assignment,
"Converting" move construction, "Converting" move assignment 

The moved-from object shall be "empty," , per [util.smartptr.shared.const], paragraph 22 and [util.smartptr.shared.assign], paragraph 4.
std::shared_ptrMove construction and move , Move assignment from a std::unique_ptrThe moved-from object is guaranteed to refer to a null pointer value, per [util.smartptr.shared.const], paragraph 29 and [util.smartptr.shared.assign], paragraph 6.
std::weak_ptrMove construction, Move Assignmentassignment,
"Converting" move construction, "Converting" move assignment 
The moved-from object shall be "empty," , per [util.smartptr.weak.const], paragraph 8, and [util.smartptr.weak.assign], paragraph 4.
std::basic_iosmove()The moved-from object is still left in an unspecified state, except that rdbuf() shall return the same value as it returned before the move, and tie() shall return 0, per [basic.ios.members], paragraph 20.
std::basic_filebufMove constructor, Move assignmentThe moved-from object is guaranteed to reference no file; other internal state is also affected, per [filebuf.cons], paragraphs 3 and 4, and [filebuf.assign], paragraph 1.
std::threadMove constructor, Move assignmentThe result from calling get_id() on the moved-from object is guaranteed to remain unchanged, but ; otherwise the object is in an unspecified state, per [thread.thread.constr], paragraph 11 and [thread.thread.assign], paragraph 2.
std::unique_lockMove constructor, Move assignmentThe moved-from object is guaranteed to be in its default state, per [thread.lock.unique.cons], paragraphs 21 and 23.
std::shared_lockMove constructor, Move assignmentThe moved-from object is guaranteed to be in its default state, per [thread.lock.shared.cons], paragraphs 21 and 23.
std::promiseMove constructor, Move assignmentThe moved-from object is guaranteed not to have any shared state, per [futures.promise], paragraphs 6 and 8.
std::futureMove constructor, Move assignmentCalling valid() on the moved-from object is guaranteed to return false, per [futures.unique_future], paragraphs 8 and 11.
std::shared_futureMove constructor, Move assignment,
"Converting" move constructor, "Converting" move assignment 
Calling valid() on the moved-from object is guaranteed to return false, per [futures.shared_future], paragraphs 8 and 11.
std::packaged_taskMove constructor, Move assignmentThe moved-from object is guaranteed not to have any shared state, per [future.task.members], paragraphs 7 and 8.

Several generic standard template library (STL) algorithms, such as std::remove() and std::unique(), remove instances of elements from a container without shrinking the size of the container. Instead, these algorithms return a ForwardIterator to indicate the partition within the container after which elements are no longer valid. The elements in the container that precede the returned iterator are valid elements with specified values, ; whereas the elements that succeed the returned iterator are valid but have unspecified values. Accessing unspecified values of elements iterated over results in unspecified behavior. Frequently, the erase-remove idiom is used to shrink the size of the container when using these algorithms.

...

Code Block
bgColor#FFcccc
langcpp
#include <iostream>
#include <string>

void g(std::string &&v) {
  std::cout << v << std::endl;
}

void f() {
  std::string s;
  for (unsigned i = 0; i < 10; ++i) {
    s.append(1, static_cast<char>('0' + i));
    g(std::move(s));
  }
}

Implementation Details

Some standard library implementations may implement the short string optimization (SSO) when implementing std::string. In such implementations, strings under a certain length are stored in a character buffer internal to the std::string object (avoiding an expensive heap allocation operation). However, such an implementation might not alter the original buffer value when performing a move operation. When the noncompliant code example is compiled with Clang 3.7 using libc++, the following output is produced:.

Code Block
0
01
012
0123
01234
012345
0123456
01234567
012345678
0123456789

...

In this compliant solution, the std::string object is initialized to the expected value on each iteration of the loop. This practice ensures that the object is in a valid, specified state prior to attempting to access it in g(), resulting in the expected output:.

Code Block
bgColor#ccccff
langcpp
#include <iostream>
#include <string>

void g(std::string &&v) {
  std::cout << v << std::endl;
}

void f() {
  for (unsigned i = 0; i < 10; ++i) {
    std::string s(1, static_cast<char>('0' + i));
    g(std::move(s));
  }
}

...

The state of a moved-from object is generally valid, but unspecified. Relying on unspecified values can lead to abnormal program termination , as well as data integrity violations.

...