#include <iostream>
#include <cstring>
#include <utility>   // std::move, std::forward
#include <vector>

// A class managing dynamic character array to demonstrate move semantics
class MyString {
private:
    char* data_;   // Pointer to heap-allocated string
    size_t len_;   // String length (without null terminator)

public:
    // Default constructor: empty string
    MyString() : data_(nullptr), len_(0) {
        data_ = new char[1];
        data_[0] = '\0';
        std::cout << "[Default Constructor] Created empty string\n";
    }

    // Construct from C-style string
    MyString(const char* str) : len_(std::strlen(str)) {
        data_ = new char[len_ + 1];
        std::strcpy(data_, str);
        std::cout << "[Constructor] Created: " << data_ << "\n";
    }

    // Copy constructor (deep copy)
    MyString(const MyString& other) : len_(other.len_) {
        data_ = new char[len_ + 1];
        std::strcpy(data_, other.data_);
        std::cout << "[Copy Constructor] Deep copy of: " << other.data_ << "\n";
    }

    // Move constructor (rvalue reference takes ownership)
    MyString(MyString&& other) noexcept : data_(other.data_), len_(other.len_) {
        other.data_ = nullptr;
        other.len_ = 0;
        std::cout << "[Move Constructor] Moved from: " << (data_ ? data_ : "nullptr") << "\n";
    }

    // Copy assignment operator (deep copy)
    MyString& operator=(const MyString& other) {
        if (this != &other) {
            std::cout << "[Copy Assignment] Deep copy of: " << other.data_ << "\n";
            delete[] data_;
            len_ = other.len_;
            data_ = new char[len_ + 1];
            std::strcpy(data_, other.data_);
        }
        return *this;
    }

    // Move assignment operator (rvalue reference)
    MyString& operator=(MyString&& other) noexcept {
        if (this != &other) {
            std::cout << "[Move Assignment] Moving from: " << (other.data_ ? other.data_ : "nullptr") << "\n";
            delete[] data_;
            data_ = other.data_;
            len_ = other.len_;
            other.data_ = nullptr;
            other.len_ = 0;
        }
        return *this;
    }

    // Destructor
    ~MyString() {
        std::cout << "[Destructor] Destroyed string: " << (data_ ? data_ : "(null)") << "\n";
        delete[] data_;
    }

    // Get string content
    const char* c_str() const {
        return data_ ? data_ : "";
    }

    // Get length
    size_t length() const {
        return len_;
    }

    // Concatenate strings (returns new object, demonstrates move semantics RVO)
    MyString operator+(const MyString& other) const {
        size_t new_len = len_ + other.len_;
        char* new_data = new char[new_len + 1];
        std::strcpy(new_data, data_);
        std::strcat(new_data, other.data_);
        MyString result;
        delete[] result.data_;
        result.data_ = new_data;
        result.len_ = new_len;
        std::cout << "[Operator+] Created temporary: " << result.data_ << "\n";
        return result;   // Return local object, compiler may perform RVO, but move constructor still available
    }
};

// Demonstrate perfect forwarding: construct any type of object and return (rvalue version)
template<typename T, typename... Args>
T createObject(Args&&... args) {
    // std::forward<Args> preserves lvalue/rvalue properties of arguments, enabling perfect forwarding
    return T(std::forward<Args>(args)...);
}

// Demonstrate function receiving rvalue reference, can safely "steal" resources
void takeOwnership(MyString&& str) {
    MyString local = std::move(str);  // Move again, transfer ownership to local
    std::cout << "[takeOwnership] Now owning: " << local.c_str() << "\n";
    // local automatically releases resources when leaving scope
}

int main() {
    std::cout << "========== 1. Basic Construction and Copy ==========\n";
    MyString a("Hello");
    MyString b = a;            // Copy constructor
    MyString c;
    c = a;                     // Copy assignment

    std::cout << "\n========== 2. Move Semantics Demonstration ==========\n";
    MyString d = std::move(a); // Move constructor (a is moved, should not use a afterwards)
    std::cout << "After move, a is now: " << a.c_str() << " (empty)\n";

    MyString e("World");
    MyString f;
    f = std::move(e);          // Move assignment (e is moved)
    std::cout << "After move, e is now: " << e.c_str() << " (empty)\n";

    std::cout << "\n========== 3. Receiving Rvalue Reference in Function ==========\n";
    takeOwnership(MyString("Temporary"));          // Temporary rvalue binds directly
    MyString g("Another");
    // takeOwnership(g);       // Error: lvalue cannot bind to rvalue reference
    takeOwnership(std::move(g));                   // Use std::move to convert lvalue to rvalue
    // g has been moved, should not use its contents anymore

    std::cout << "\n========== 4. Perfect Forwarding to Create Objects ==========\n";
    // Create object using lvalue (calls copy constructor)
    MyString original("Original");
    auto copy = createObject<MyString>(original);
    // Create object using rvalue (calls move constructor)
    auto moved = createObject<MyString>(MyString("Temporary"));
    // Pass string literal directly, will call MyString(const char*) constructor
    auto literal = createObject<MyString>("Literal");

    std::cout << "\n========== 5. Move Semantics in Containers (Performance Optimization) ==========\n";
    std::vector<MyString> vec;
    vec.reserve(3);
    std::cout << "Pushing temporary objects:\n";
    vec.push_back(MyString("First"));    // Temporary object -> move constructor
    vec.push_back(MyString("Second"));
    vec.push_back(MyString("Third"));

    std::cout << "\nPushing existing object with std::move:\n";
    MyString existing("Existing");
    vec.push_back(std::move(existing));  // Explicitly transfer ownership

    std::cout << "\nContents of vector:\n";
    for (const auto& item : vec) {
        std::cout << " - " << item.c_str() << "\n";
    }

    std::cout << "\n========== 6. Operator Returns Temporary Object ==========\n";
    MyString hello("Hello ");
    MyString world("World");
    MyString helloWorld = hello + world;   // Temporary object + move constructor (or RVO)
    std::cout << "Result of concatenation: " << helloWorld.c_str() << "\n";

    std::cout << "\n========== Program End, All Objects Will Be Destructed ==========\n";
    return 0;
}

results matching ""

    No results matching ""