c++ - 如何使用移动构造函数释放内存
问题描述
我正在尝试创建自己的向量,这是一个介绍我遇到的问题的最小示例:
class DemoVector {
public:
DemoVector() : capacity_(1), size_(0) {
data_ = new int[1];
}
DemoVector(DemoVector&& rhs) {
data_ = std::move(rhs.data_);
size_ = rhs.size_;
capacity_ = rhs.capacity_;
}
~DemoVector() {
delete[] data_;
}
void PushBack(const int &v) {
// doesn't matter
}
private:
int *data_;
size_t capacity_;
size_t size_;
};
测试:
TEST_CASE("Test") {
DemoVector b;
b.PushBack(1);
DemoVector c(std::move(b));
}
我有一个问题,我明白为什么。我有两个指向同一内存的对象。第二个析构函数尝试释放已被第一个析构函数释放的内存。
但我不知道如何解决它。谢谢您的帮助。
解决方案
std::move(rhs.data_)
实际上并没有移动任何东西。std::move
无非是一个有名的演员表。它产生一个允许移动语义发生的右值引用。但是对于原始类型,它只是一个复制操作。指针正在被复制,因此您最终会得到两个包含相同地址的指针。由于您不希望源对象仍然指向同一个缓冲区,因此只需修改它。这就是为什么移动语义是围绕非常量引用构建的。
移动构造函数现在很常见,因此有一个标准实用程序 (C++14) 可以帮助编写它们,使代码表现得更符合您的预期。是std::exchange
。你可以简单地写
DemoVector(DemoVector&& rhs)
: data_(std::exchange(rhs.data_, nullptr))
, size_(std::exchange(rhs.size_ , 0))
, capacity_(std::exchange(rhs.capacity_ , 0))
{}
并且所有值都得到了适当的调整。std::exchange
修改其第一个参数以保存第二个参数的值。最后,它返回第一个参数的旧值。在单行初始化中移动值非常方便。
推荐阅读
- python - Is It Important To Specify Data Types For Speedy NumPy computations?
- python - Python - How can I create a new list based on the values of another list?
- python - Python:如何在子类初始化时继承父类的所有当前属性?
- json - 从资产文件夹中的 JSON 文件而不是 url 中获取数据
- c# - 是否可以使用 c# 将文件上传到 SharePoint Online 中的自定义列表
- ios - 如何绘制水平阴影?
- ios - 如何使用 Swift 中的 url 从 firebase 正确检索数据?
- python - GLFW 不再在 Python 中工作(错误 65543)
- json - 颠簸变换嵌套数组和对象
- c# - 我有异常 Unexpected sub-type: ExampleNameSpace.ClassB while Serializing in protobuf-net