【问题标题】:Copying vs Moving while casting objects在投射对象时复制与移动
【发布时间】: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&amp;&amp; ) 会编译并可能做一个reinterpret_cast 给你留下未定义的行为。另见en.cppreference.com/w/cpp/utility/move
  • 与问题无关的注释:使用swap 实现移动赋值/构造函数似乎是一个简单的解决方案,但它可能导致意外的订单资源被释放,因为作为源的对象移动的可能会比移动的目标存活更长时间......另外Vector缺少一个虚拟析构函数......
  • 但是你为什么希望代码打印任何东西呢? ColumnVector cv = ( ColumnVector&amp;&amp; )v; 告诉编译器使用ColumnVector(ColumnVector&amp;&amp; v) 构造cv,假设未定义行为没有问题,则将数据交换出存储v 数据的向量,这意味着v 之后为空;您打印的是 v 的内容,而不是 cv 的内容...
  • @fabian 我在析构函数中无事可做,因此我不需要一个
  • @andrei81 这并不完全正确。您的构造函数负责删除向量,即使您不需要为此定义构造函数。在这种情况下,您可能很幸运,并且没有数据 ColumnVector 添加到 Vector,因此它可能适用于您的情况,但不能保证您能够正确删除动态分配的 ColumnVector是通过Vector* 引用的,这是你想不到的......

标签: c++ oop casting move move-semantics


【解决方案1】:

您不需要编写复制和移动构造函数,因为如果唯一的行为是复制/移动std::vector 成员,编译器将隐式生成它们。

顺便说一句,您可能希望将您的ColumnVector 实现为Vector(类似于std::string_view)的视图,这样就没有任何动作了。

【讨论】:

    猜你喜欢
    • 2015-01-10
    • 2018-12-08
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多