2

Consider the following example:

#include <iostream>
#include <vector>

class A {
public:
    A(const A&) = default;
    A(A&&) = default;
    A& operator=(const A&) = default;
    A& operator=(A&&) = default;

    A() = default;
    ~A() {
        std::cout << "~A()\n";
    }
};

int main() {
    std::vector<A> v1;
    std::vector<A> v2;

    v1.emplace_back();
    v1 = std::move(v2);
    std::cout << "moved\n";
}

The output is:

~A()
moved

My question is: Can I rely on std::move to destruct elements inside v1? Or, in other words, is the output above guaranteed, or can I get:

moved
~A()

It would be surprising if the latter is possible, but I didn't find a definite answer, and didn't find anything explicit in the standard. That could happen if the move assignment operator is implemented with std::swap or similar, but I didn't find a solid answer regarding whether that's valid or not.

Paul
  • 6,061
  • 6
  • 39
  • 70

1 Answers1

2

While swapping would be a valid implementation for move assignment in general, standard library containers have extra requirements. Table 73:

Expression: a = rv
Return type: X&
Operational semantics: All existing elements of a are either move assigned to or destroyed
Assertion/Note pre-/post-condition: Postconditions: a is equal to the value that rv had before this assignment
Complexity: linear

So a swap wouldn't suffice, since that wouldn't move-assign to or destroy the original v1[0]

Artyer
  • 31,034
  • 3
  • 47
  • 75