关于含独有指针对象的移动构造与赋值指令数的疑问
Great question—this confusion boils down to a critical rule of move semantics: after transferring ownership of the pointer, we must leave the source rvalue object in a valid, destructible state (almost always by setting its pointer to nullptr). Let’s break this down for both operations to clear up the missing counts.
Move Constructor: 1 Load, 2 Stores
Your initial count misses the second mandatory store, which ensures the source object doesn’t cause double-frees later. Here’s a typical safe implementation for a class with an owning pointer:
MyClass(MyClass&& rhs) noexcept : ptr(rhs.ptr) // 1. Load `rhs.ptr` from memory; 2. Store that value into `this->ptr` (1 load, 1 store so far) { rhs.ptr = nullptr; // 3. Store `nullptr` into `rhs.ptr` (this is the second required store) }
We can’t skip that final store. If we left rhs.ptr pointing to the memory we just took ownership of, when rhs is destroyed (even as a temporary), its destructor would try to free that same memory—leading to a catastrophic double-free error. Nulling out the source is non-negotiable for safe move behavior.
Move Assignment Operator: 2 Loads, 2 Stores
Your count overlooks two key operations: resetting the source pointer, and loading the left-hand side’s existing pointer to clean it up before taking the new one. Here’s a standard safe implementation:
MyClass& operator=(MyClass&& rhs) noexcept { if (this != &rhs) { // Address checks don't count toward pointer value loads/stores here delete ptr; // 1. Load `this->ptr` (left-hand side's existing pointer) to free old memory (first load) ptr = rhs.ptr; // 2. Load `rhs.ptr` (second load); 3. Store that value into `this->ptr` (first store) rhs.ptr = nullptr; // 4. Store `nullptr` into `rhs.ptr` (second store) } return *this; }
Mapping this to the official count:
- 2 Loads: We read the left-hand side’s pointer (to delete its old memory) and the right-hand side’s pointer (to take ownership of the new memory).
- 2 Stores: We write the new pointer to the left-hand side, and write
nullptrto the right-hand side to invalidate it.
Even if you optimized out the delete (e.g., if the left-hand pointer was already null), the standard move semantics still require nulling out the source rvalue—so that second store remains mandatory.
内容的提问来源于stack exchange,提问作者LeastSquaresWonderer

