【发布时间】:2020-06-04 04:19:53
【问题描述】:
我正在执行一些关于移动语义的测试,我的班级行为对我来说似乎很奇怪。
鉴于模拟类VecOfInt:
class VecOfInt {
public:
VecOfInt(size_t num) : m_size(num), m_data(new int[m_size]) {}
~VecOfInt() { delete[] m_data; }
VecOfInt(VecOfInt const& other) : m_size(other.m_size), m_data(new int[m_size]) {
std::cout << "copy..." <<std::endl;
std::copy(other.m_data, other.m_data + m_size, m_data);
}
VecOfInt(VecOfInt&& other) : m_size(other.m_size) {
std::cout << "move..." << std::endl;
m_data = other.m_data;
other.m_data = nullptr;
}
VecOfInt& operator=(VecOfInt const& other) {
std::cout << "copy assignment..." << std::endl;
m_size = other.m_size;
delete m_data;
m_data = nullptr;
m_data = new int[m_size];
m_data = other.m_data;
return *this;
}
VecOfInt& operator=(VecOfInt&& other) {
std::cout << "move assignment..." << std::endl;
m_size = other.m_size;
m_data = other.m_data;
other.m_data = nullptr;
return *this;
}
private:
size_t m_size;
int* m_data;
};
-
好的案例
当我就地插入单个值:
int main() { std::vector<VecOfInt> v; v.push_back(10); return 0; }然后它给了我以下输出(我认为很好):
move... -
奇怪的情况
当我就地插入三个不同的值:
int main() { std::vector<VecOfInt> v; v.push_back(10); v.push_back(20); v.push_back(30); return 0; }那么输出调用复制构造函数3次:
move... move... copy... move... copy... copy...
我在这里缺少什么?
【问题讨论】:
-
附带说明,
operator=(VecOfInt const&)应该在复制之前检查自分配,这不是正确的delete'ingm_data。并且operator=(VecOfInt&&)正在泄漏内存,因为m_data指向的原始数组丢失了。您可以通过按值传递other并让其构造函数在复制和移动操作之间做出决定,将两个operator=组合成一个实现。并查看copy-swap idiom 以避免泄漏。 -
另外,
operator=在分配新内存之前会改变*this的状态,因此如果抛出异常,则您的对象已损坏。 -
您应该将
VecOfInt更改为在内部使用std::vector<int>,然后所有这些问题都会消失。 -
由于随着向量的增长,代码缺少
v.reserve(3);,因此必须将对象复制到调整大小的向量。
标签: c++ c++11 stdvector move-semantics move-constructor