手撕string 理解右值

class Mystring
{
public:
    Mystring() : data(new char[1]{'\0'}), length(0) {};
    ~Mystring() {
        delete []data;
    }
    Mystring(const char * str) { // 普通构造 带explicit 无法实现 Mystring a = "123"
        if (!str) {
            data = new char[1]{'\0'};
            length = 0;
        } else {
            length = std::strlen(str);
            data = new char[length + 1];
            strcpy(data, str);
        }
    }
    Mystring(const Mystring &b) { // 拷贝构造 深拷贝自己可控制
        length = b.length;
        data = new char[length + 1];
        strcpy(data, b.data);
    }

    Mystring(Mystring && b) noexcept : data(b.data), length(b.length){ 
        b.data = nullptr; // 移动拷贝 释放b对象 noexcept 适配vector容器检查 vector push back 扩容会调用移动拷贝 速度快
        b.length = 0;
    }

    Mystring &operator=(const Mystring &b) { // 拷贝赋值 
        if (this == &b) {
            return *this;
        }
        delete [] data;
        length = b.length;
        data = new char[length + 1];
        std::strcpy(data, b.data);
        return *this;
    }

    Mystring &operator=(Mystring &&b) noexcept { // 移动赋值 noexpect同理
        if (this == &b) {
            return *this;
        }
        delete [] data;
        length = b.length;
        data = b.data;
        b.data = nullptr;
        b.length = 0;
        return *this;
    }
    
    Mystring operator+(const Mystring &b) {
        Mystring res;
        res.length = b.length + length;
        res.data = new char[res.length + 1];
        strcpy(res.data, data);
        strcat(res.data, b.data);
        return res;
    }
    
    char &operator[](size_t len) {
        return data[len];
    }
    
    const char &operator[](size_t len) const{
        return data[len];
    }
    
    const char* c_str() const{
        return data;
    }

private:
    char *data;
    size_t length;
};

    Mystring a = "123"; // 有参构造 隐式转换 
    Mystring b = a; // 拷贝构造
    Mystring c;
    Mystring e;
    c = a; // 拷贝赋值
    Mystring d = std::move(a); // 移动构造
    e = std::move(b); // 移动赋值

<think>嗯,我现在得仔细想想用户的问题:如何理解引用。用户是希望我作为C++专家详细解释这个概念。首先,我需要回顾引用的基本定义和它在C++中的作用。 引用是C++11引入的重要特性,主要用于实现移动语义和完美转发。那什么是呢?通常是临时对象,比如函数返回的临时或者字面量。引用的声明方式是使用&&,例如int&& r = 5;。 接下来,我需要解释引用的主要用途。移动语义是关键点之一。传统的拷贝构造函数会复制资源,而移动构造函数则通过“窃取”资源来提升效率。比如,当处理临时对象时,使用移动构造可以避免不必要的深拷贝,这对管理大量资源的类(如std::vector)尤为重要。 然后是完美转发,这允许函数模板在传递参数时保持其类别(左)。通过std::forward,可以确保参数在传递过程中保持原有的类型,从而正确选择重载函数。这在使用通用引用(T&&)时特别有用,比如在工厂函数中创建对象时保持参数类型。 另外,我需要提到引用的生命周期延长特性。绑定引用到临时对象会延长其生命周期,使临时对象在引用存在期间保持有效。这点可能容易被忽略,但对理解引用的行为很重要。 可能还需要举一些代码示例来说明移动构造函数和移动赋运算符的实现,比如一个简单的动态数组类。同时,要指出移动操作后源对象应处于有效但不确定的状态,比如将源指针置空,防止重复释放资源。 用户可能存在的疑问包括:引用和左引用的区别,std::move的作用,以及何时应该使用移动语义。此外,可能还需要解释通用引用和完美转发的应用场景,以及如何避免常见的错误,比如在移动后继续使用源对象。 总结时,要强调引用如何优化性能,减少不必要的拷贝,并支持更高效的资源管理。同时,要提醒用户注意移动后的对象状态,确保程序的正确性。</think><< 引用是C++11引入的核心特性,主要用于实现移动语义(Move Semantics)和完美转发(Perfect Forwarding)。以下是其核心要点: ### 1. **的定义** - ****是临时对象或字面量,不能被取地址(如 `42`、函数返回的临时对象)。 - **引用**通过 `&&` 声明,例如 `int&& r = 10;`,专门绑定到。 ### 2. **核心作用** - **移动语义**:通过“窃取”资源避免深拷贝。例如,移动构造函数将资源从临时对象转移,而非复制: ```cpp class Vector { public: // 移动构造函数 Vector(Vector&& other) noexcept : data_(other.data_), size_(other.size_) { other.data_ = nullptr; // 置空源对象指针 } private: int* data_; size_t size_; }; ``` - **完美转发**:保持参数的类别(左/),通过 `std::forward` 实现: ```cpp template<typename T> void wrapper(T&& arg) { target(std::forward<T>(arg)); // 转发时保留原类型 } ``` ### 3. **生命周期延长** - 引用绑定到临时对象时,临时对象的生命周期被延长至与引用相同: ```cpp const std::string& s = std::string("Hello"); // 合法:延长生命周期 ``` ### 4. **`std::move` 的作用** - 将左显式转换为引用,触发移动语义: ```cpp std::vector<int> v1 = {1, 2, 3}; std::vector<int> v2 = std::move(v1); // v1 现在为空 ``` ### 5. **注意事项** - 移动后的源对象应处于有效但未定义的状态(如置空指针)。 - 移动构造函数和移动赋运算符应标记为 `noexcept`,确保容器操作的安全性。 ### 代码示例 ```cpp // 移动赋运算符 Vector& Vector::operator=(Vector&& other) noexcept { if (this != &other) { delete[] data_; // 释放当前资源 data_ = other.data_; // 转移资源 size_ = other.size_; other.data_ = nullptr; // 置空源对象 } return *this; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值