移动构造函数问题

C++11之后出现了移动构造函数这么一个东西,stl里面的类我的理解vector list都有去实现这个东西。

现在有几个问题需要确认:

  1. 移动构造函数的实现方式
  2. 默认移动构造函数是否会被调用
  3. 移动构造函数的使用场景

#include <iostream>  
  
class MemoryBlock  
{  
public:  
  
    // 构造器(初始化资源)  
    explicit MemoryBlock(size_t length)  
        : _length(length)  
        , _data(new int[length])  
    {  
    }  
  
    // 析构器(释放资源)  
    ~MemoryBlock()  
    {  
        if (_data != nullptr)  
        {  
            delete[] _data;  
        }  
    }  
  
    // 拷贝构造器(实现拷贝语义:拷贝that)  
    MemoryBlock(const MemoryBlock& that)  
        // 拷贝that对象所拥有的资源  
        : _length(that._length)  
        , _data(new int[that._length])  
    {  
        std::copy(that._data, that._data + _length, _data);  
    }  
  
    // 拷贝赋值运算符(实现拷贝语义:释放this + 拷贝that)  
    MemoryBlock& operator=(const MemoryBlock& that)  
    {  
        if (this != &that)  
        {  
            // 释放自身的资源  
            delete[] _data;  
  
            // 拷贝that对象所拥有的资源  
            _length = that._length;  
            _data = new int[_length];  
            std::copy(that._data, that._data + _length, _data);  
        }  
        return *this;  
    }  
  
    // 移动构造器(实现移动语义:移动that)  
    MemoryBlock(MemoryBlock&& that)  
        // 将自身的资源指针指向that对象所拥有的资源  
        : _length(that._length)  
        , _data(that._data)  
    {  
        // 将that对象原本指向该资源的指针设为空值  
        that._data = nullptr;  
        that._length = 0;  
    }  
  
    // 移动赋值运算符(实现移动语义:释放this + 移动that)  
    MemoryBlock& operator=(MemoryBlock&& that)  
    {  
        if (this != &that)  
        {  
            // 释放自身的资源  
            delete[] _data;  
  
            // 将自身的资源指针指向that对象所拥有的资源  
            _data = that._data;  
            _length = that._length;  
  
            // 将that对象原本指向该资源的指针设为空值  
            that._data = nullptr;  
            that._length = 0;  
        }  
        return *this;  
    }  
private:  
    size_t _length; // 资源的长度  
    int* _data; // 指向资源的指针,代表资源本身  
};  
  
MemoryBlock f() { return MemoryBlock(50); }  
  
int main()  
{  
    MemoryBlock a = f();            // 调用移动构造器,移动语义  
    MemoryBlock b = a;              // 调用拷贝构造器,拷贝语义  
    MemoryBlock c = std::move(a);   // 调用移动构造器,移动语义  
    a = f();                        // 调用移动赋值运算符,移动语义  
    b = a;                          // 调用拷贝赋值运算符,拷贝语义  
    c = std::move(a);               // 调用移动赋值运算符,移动语义  
}  

上面代码中有移动构造函数的实现方式,就是把原来对象里面的成员变量给到当前对象,然后把原对象里面的成员置空,就是把A的东西搬运到B里面,然后A里面就没有东西,其实我觉得A里面的东西置空不置空无所谓,这个要说右值构造函数的调用时机。

右值构造函数的调用时机

#include <iostream>     // std::cout
class A {
public:
    A() {
        cout << "A::A() 构造函数" << this << endl;
        str = "A";
    }
    ~A() {
        cout << "析构函数" << this << endl;
    }

    A(const A &a) {
        cout << "拷贝构造函数" << this << endl;
        str = a.str;
    }

    A& operator=(const A& a) {
        cout << "赋值运算符" << this << endl;
        str = a.str;
        return *this;
    }

    A(const A&& a)
    : str(a.str) {
        cout << "移动构造" << this << endl;
    }

    A(const string &s) {
        cout << "构造函数 " << this << endl;
        str = s;
    }

    string str;
    shared_ptr<B> ptr;
};

A getA() {
    A a("aaaaaaa");
    return a;
}

A* GetA() {
    A* p = new A("bbbbbbbbbbbb");
    return p;
}

void main() {
    {
        A a = getA();
        cout << a.str << endl;
    }

    cout << endl;
    cout << endl;

    A* b = GetA();
    delete b;
}
/**输出**
构造函数 00000016650FF8D8
移动构造00000016650FFAC8
析构函数00000016650FF8D8
aaaaaaa
析构函数00000016650FFAC8


构造函数 000001A81A4983E0
析构函数000001A81A4983E0
*/

这里显示的实现了右值构造函数,在getA()返回时,他会被调用,如果去掉右值构造函数,他会调用拷贝构造函数,但是如果我们没有实现右值构造也没有实现拷贝构造,那他会不会调用默认右值构造函数呢,这个问题知乎上面有人讨论过,我直接在这里记录结论,可能还有待商榷先,先给出链接 C++默认移动构造函数有什么用? - 知乎

c++ Primer:只有当一个类没有定义任何自己的拷贝控制函数,并且其所有数据成员都可以移动构造或移动赋值时,编译器会为它合成移动构造函数.........................与拷贝操作不同,编译器根本不会为某些类合成移动操作。特别是,如果一个类定义了自己的拷贝构造函数、拷贝赋值运算符或者析构函数,编译器就不会为它合成移动构造函数和移动赋值运算符了。.... ~嗯,这样看来合理,指针所指向的资源不需要析构(也就没定义析构函数),那就默认生成移动构造函数也没问题~

你强制使用std::move那就会被强制调用,那些没有定义移动构造的成员变量的信息应该就会被丢失了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值