CodeNebula
C++11coreintermediate

Move Assignment Operator (C++11 Addition)

C++11 · Modern Revolution · Compiler flag: -std=c++11

Explanation

An assignment operator that transfers resources from a temporary object to an existing object, releasing the target's old resources and taking ownership of the source's resources.

Real-World Scenario

Reassign a network connection handler to a new connection by moving the socket data instead of duplicating it.

Quick Snippet

snippet.cpp
class Connection {
    int* socket;
public:
    Connection& operator=(Connection&& other) noexcept {
        if (this != &other) {
            delete socket;
            socket = other.socket;
            other.socket = nullptr;
        }
        return *this;
    }
};

Full Example

move_assignment.cpp
// CodeNebula - C++11 Example: Move Assignment Operator
// Compile: g++ -std=c++11 -Wall -Wextra -o example move_assignment.cpp

// Demonstrates implementing the move assignment operator. Unlike copy
// assignment, move assignment transfers resources without allocation,
// providing O(1) reassignment for resource-managing classes.

#include <iostream>
#include <cstring>
#include <utility>
#include <vector>

// Real-world scenario: a dynamic array class
class DynArray {
    int* data_;
    std::size_t size_;
    std::string tag_;

    void dump(const char* label) const
    {
        std::cout << "  [" << label << "] " << tag_
                  << " (size=" << size_ << ")" << std::endl;
    }

public:
    DynArray(const std::string& tag, std::initializer_list<int> init)
        : data_(new int[init.size()]), size_(init.size()), tag_(tag)
    {
        std::copy(init.begin(), init.end(), data_);
        dump("Ctor");
    }

    // Copy assignment (deep copy)
    DynArray& operator=(const DynArray& other)
    {
        if (this != &other) {
            delete[] data_;
            size_ = other.size_;
            data_ = new int[size_];
            std::copy(other.data_, other.data_ + size_, data_);
            tag_ = other.tag_ + "_copy";
            dump("Copy=");
        }
        return *this;
    }

    // Move assignment operator
    DynArray& operator=(DynArray&& other) noexcept
    {
        if (this != &other) {
            // 1. Release our current resources
            delete[] data_;

            // 2. Steal the source's resources
            data_ = other.data_;
            size_ = other.size_;
            tag_  = std::move(other.tag_);

            // 3. Leave source in valid empty state
            other.data_ = nullptr;
            other.size_ = 0;

            dump("Move=");
        }
        return *this;
    }

    // Move constructor
    DynArray(DynArray&& other) noexcept
        : data_(other.data_), size_(other.size_), tag_(std::move(other.tag_))
    {
        other.data_ = nullptr;
        other.size_ = 0;
        dump("MoveCtor");
    }

    ~DynArray()
    {
        std::cout << "  [Dtor]     " << (tag_.empty() ? "(empty)" : tag_) << std::endl;
        delete[] data_;
    }

    void print() const
    {
        std::cout << "  " << (tag_.empty() ? "(empty)" : tag_) << ": [";
        for (std::size_t i = 0; i < size_; ++i) {
            if (i > 0) std::cout << ", ";
            std::cout << data_[i];
        }
        std::cout << "]" << std::endl;
    }

    std::size_t size() const { return size_; }
};

int main()
{
    // ------------------------------------------------------------------
    // 1. Move assignment via std::move
    // ------------------------------------------------------------------
    std::cout << "=== Move assignment ===" << std::endl;
    DynArray a("A", {1, 2, 3});
    DynArray b("B", {10, 20});
    a.print();
    b.print();

    a = std::move(b);   // move assignment: a steals b's resources
    std::cout << "  After a = std::move(b):" << std::endl;
    a.print();
    std::cout << "  b.size() = " << b.size() << std::endl;
    std::cout << std::endl;

    // ------------------------------------------------------------------
    // 2. Move assignment from temporary (rvalue)
    // ------------------------------------------------------------------
    std::cout << "=== Move from temporary ===" << std::endl;
    DynArray c("C", {100});
    c.print();
    c = DynArray("Temp", {7, 8, 9});   // temporary -> move assignment
    c.print();
    std::cout << std::endl;

    // ------------------------------------------------------------------
    // 3. Copy assignment for comparison
    // ------------------------------------------------------------------
    std::cout << "=== Copy assignment (for comparison) ===" << std::endl;
    DynArray d("D", {5, 6});
    DynArray e("E", {50, 60, 70});
    d = e;   // copy assignment: allocates new memory
    d.print();
    e.print();   // e is unchanged
    std::cout << std::endl;

    // ------------------------------------------------------------------
    // 4. Chain of move assignments
    // ------------------------------------------------------------------
    std::cout << "=== Chained moves ===" << std::endl;
    DynArray x("X", {1});
    DynArray y("Y", {2});
    DynArray z("Z", {3});
    x = std::move(y);
    y = std::move(z);   // y was moved-from, now gets z's resources
    x.print();
    y.print();
    std::cout << "  z.size() = " << z.size() << std::endl;

    std::cout << std::endl << "=== Cleanup ===" << std::endl;
    return 0;
}

/*
Expected output:

=== Move assignment ===
  [Ctor]     A (size=3)
  [Ctor]     B (size=2)
  A: [1, 2, 3]
  B: [10, 20]
  [Move=]    B (size=2)
  After a = std::move(b):
  B: [10, 20]
  b.size() = 0

=== Move from temporary ===
  [Ctor]     C (size=1)
  C: [100]
  [Ctor]     Temp (size=3)
  [Move=]    Temp (size=3)
  [Dtor]     (empty)
  Temp: [7, 8, 9]

=== Copy assignment (for comparison) ===
  [Ctor]     D (size=2)
  [Ctor]     E (size=3)
  [Copy=]    E_copy (size=3)
  E_copy: [50, 60, 70]
  E: [50, 60, 70]

=== Chained moves ===
  [Ctor]     X (size=1)
  [Ctor]     Y (size=1)
  [Ctor]     Z (size=1)
  [Move=]    Y (size=1)
  [Move=]    Z (size=1)
  Y: [2]
  Z: [3]
  z.size() = 0

=== Cleanup ===
  [Dtor]     (empty)
  [Dtor]     Z
  [Dtor]     Y
  [Dtor]     E
  [Dtor]     E_copy
  [Dtor]     Temp
  [Dtor]     (empty)
  [Dtor]     B
*/
Run command
g++ -std=c++11 -Wall -Wextra -o example move_assignment.cpp