我的move构造函数和move赋值运算符写得好吗?

问题描述

我要在此结构中添加move构造函数和move赋值运算符。 有人可以告诉我他们写得好吗? 当我在没有这两种方法的情况下运行代码时,一切正常,但是,当我添加这两种方法时,则无法正常工作。 非常感谢

    struct Data {
        Data() = default;
    
        Data(const unsigned int _x) : data(new unsigned char[_x]),size(_x) {}
    
        Data(const Data &_d) : data(new unsigned char[_d.size]),size(_d.size) {
            memcpy(data,_d.data,_d.size);
        }
    
        ~Data() {
            delete[] data;
            size = 0;
        };
    
        Data& operator=(const Data &_d) {
            if (this == &_d) {
                return *this;
            }
            unsigned char *tmp(new unsigned char[_d.size]);
            memcpy(tmp,_d.size);
            delete[] data;
            data = tmp;
            size = _d.size;
            return *this;
        }
    

这是我的move构造函数,应该先删除数据,如果大小不相等,再分配新大小的数据吗?

Data(Data &&_d)
    {
        data = _d.data;
        _d.data = nullptr;
        size = _d.size;
        _d.size = 0;
    }

这是我的移动分配运算符

    Data& operator=(Data&& _d)
    {
        if (this != &_d)
        {
            delete[] data;
            data = _d.data;
            _d.data = nullptr;
            size = _d.size;
            _d.size = 0;
        }
        return *this;
    }
    
        unsigned char *data = nullptr;
        unsigned int size = 0;
    };

解决方法

您已经在课堂上提供了begin和end方法。可能您想使用STL。在这种情况下,如果要提供强大的异常保证,则应添加noexcept。如果STL容器为noexcept(false),则它们不会使用您的move构造函数/分配。

Data& operator=(Data&& _d) noexcept
{
    if (this != &_d)
    {
        delete[] data;
        data = _d.data;
        _d.data = nullptr;
        size = _d.size;
        _d.size = 0;
    }
    return *this;
}


Data(Data &&_d) noexcept
{
    data = _d.data;
    _d.data = nullptr;
    size = _d.size;
    _d.size = 0;
}

Here you can read about it

STL容器在调整大小时只能使用move构造函数 如果该构造函数没有破坏其强异常的操作 安全保证。用更简单的语言,它不会使用移动 对象的构造函数(如果可以抛出异常)。这是 因为如果在移动过程中引发了异常,则 被处理的内容可能会丢失,就像在复制构造函数中那样 原始不会改变。

,

您的验证码是正确的。

但是还有一种使用https://youtu.be/KVOiKz-ddwk来实现移动分配的模式:

Data& operator=(Data&& _d)
{
    std::swap(data,_d.data);
    std::swap(s,_d.size);
    return *this;
}

在此,调用_d析构函数时将释放旧数据。

这不是“更正确的方法”,但是更容易编写,并且留下更少的空间来忘记正确配置资源。

移动构造函数可以重用移动分配:

Data(Data&& _d)
    : this() 
{
    *this = std::move(_d);
}

同样,这不是更好的方法,但是可以减少重复代码的数量。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...