【发布时间】:2021-07-24 13:05:48
【问题描述】:
我正在尝试为线性代数列向量实现一个类。我有以下代码 sn-p,我尝试在不复制任何内容的情况下投射对象。
#include <iostream>
#include <fstream>
#include <cassert>
#include <vector>
using namespace std;
class Vector
{
public:
std::vector<int> vect;
public:
Vector() = default;
Vector(const Vector& v):vect(v.vect){ };
Vector(Vector&& v)
{
vect.swap(v.vect);
}
Vector(const std::vector<int>& v)
{
vect = v;
}
Vector(std::vector<int>&& v)
{
vect.swap(v);
}
auto begin()
{
return vect.begin();
}
auto end()
{
return vect.end();
}
};
class ColumnVector: public Vector
{
public:
ColumnVector() = default;
ColumnVector(const ColumnVector& v)
{
this->vect = v.vect;
}
ColumnVector(ColumnVector&& v)
{
this->vect.swap(v.vect);
}
ColumnVector(Vector&& v)
{
this->vect.swap(v.vect);
}
};
int main()
{
Vector v(vector<int>({ 1, 2, 3, 4, 5 }));
ColumnVector cv = ( ColumnVector&& )v;
for ( auto it = v.begin(); it != v.end(); it++ )
cout << *it << " ";
// nothing printed -- seems that data have been moved
for ( auto it = cv.begin(); it != cv.end(); it++ )
cout << *it << " ";
// 1 2 3 4 5
}
我尝试在不进行任何复制的情况下投射对象。速度很重要,所以我想知道我是否做得对。另外,伙计们,你们有什么优化技巧可以用于这段代码 sn-p 吗?
最终:
我决定使用std::move,它可以尽快完成这项工作。
【问题讨论】:
-
"...我想知道我是否做得对..." 使用
std::move- 为什么因为如果你打错了( ColumnVector&& )会编译并可能做一个reinterpret_cast给你留下未定义的行为。另见en.cppreference.com/w/cpp/utility/move -
与问题无关的注释:使用
swap实现移动赋值/构造函数似乎是一个简单的解决方案,但它可能导致意外的订单资源被释放,因为作为源的对象移动的可能会比移动的目标存活更长时间......另外Vector缺少一个虚拟析构函数...... -
但是你为什么希望代码打印任何东西呢?
ColumnVector cv = ( ColumnVector&& )v;告诉编译器使用ColumnVector(ColumnVector&& v)构造cv,假设未定义行为没有问题,则将数据交换出存储v数据的向量,这意味着v之后为空;您打印的是v的内容,而不是cv的内容... -
@fabian 我在析构函数中无事可做,因此我不需要一个
-
@andrei81 这并不完全正确。您的构造函数负责删除向量,即使您不需要为此定义构造函数。在这种情况下,您可能很幸运,并且没有数据
ColumnVector添加到Vector,因此它可能适用于您的情况,但不能保证您能够正确删除动态分配的ColumnVector是通过Vector*引用的,这是你想不到的......
标签: c++ oop casting move move-semantics