c++ - 在重载 vector 求和中移动分配

标签 c++ class vector move-constructor copy-elision

我正在阅读C++导览(第5.2节“复制和移动”)。按照书中的说明,我建立了一个名为Vector的容器(它模仿std::vector)。我的目标是有效地执行以下(元素方面)的求和:

Vector r = x + y + z;

根据这本书,如果我没有移动分配和构造函数,+运算符将最终不必要地复制Vector。因此,我实现了移动分配和构造函数,但是我认为当我运行Vector r = x + y + z;时,编译器仍未使用它们。我想念什么?我感谢任何反馈。下面是我的代码。我希望看到输出Move assignment,但是没有输出。 (总结部分起作用,我不确定只是搬家生意)

代码
// Vector.h
class Vector{

public:
    explicit Vector(int);
    Vector(std::initializer_list<double>);
    // copy constructor
    Vector(const Vector&);
    // copy assignment
    Vector& operator=(const Vector&);
    // move constructor
    Vector(Vector&&);
    // move assignment
    Vector& operator=(Vector&&);
    ~Vector(){delete[] elem;}
    double& operator[](int) const;
    int size() const;
    void show();
    friend std::ostream& operator<< (std::ostream& out, const Vector& vec);

private:
    int sz;
    double* elem;
};

Vector operator+(const Vector&,const Vector&);

// Vector.cpp

Vector::Vector(std::initializer_list<double> nums) {
    sz = nums.size();
    elem = new double[sz];
    std::initializer_list<double>::iterator it;
    int i = 0;
    for (it=nums.begin(); it!=nums.end(); ++it){
        elem[i] = *it;
        ++i;
    }
}

Vector::Vector(Vector&& vec) {
    sz = vec.sz;
    vec.sz = 0;
    elem = vec.elem;
    vec.elem = nullptr;
    std::cout<<"Move constructor"<<std::endl;
}

Vector& Vector::operator=(Vector&& vec) {
    if (this == &vec){
        return *this;
    }
    sz = vec.sz;
    vec.sz = 0;
    elem = vec.elem;
    vec.elem = nullptr;
    std::cout<<"Move assignment"<<std::endl;
    return *this;

Vector operator+(const Vector& vec1, const Vector& vec2){
    if (vec1.size() != vec2.size()){
        throw std::length_error("Input vectors should be of the same size");
    }
    Vector result(vec1.size());
    for (int i=0; i!=vec1.size(); ++i){
        result[i] = vec1[i]+vec2[i];
    }
    return result;
}
}
// Main
int main() {
    Vector x{1,1,1,1,1};
    Vector y{2,2,2,2,2};
    Vector z{3,3,3,3,3};
    Vector r = x + y + z;
} // Here I expect the output: Move assignment, but I get no output.

最佳答案

发生移动省略。

根据C++ 17标准(12.8复制和移动类对象)

31 When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization.122 This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

(31.3) — when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move



因此,省略了move构造函数。由表达式x + y + z;创建的第二个临时对象被直接构建为对象r。
Vector r = x + y + z;

还应考虑到运算符的return语句中存在移动省略符

(31.1) — in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cvunqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value



因此,在x + y表达式中创建的临时对象(在运算符内)将在( x + y ) + z表达式中移动(即相对于return语句的省略号-在引号之前),它将由常量左值引用和新的临时对象使用在此表达式中创建的对象将被构建为r。

总体而言,此代码段
Vector x{1,1,1,1,1};
Vector y{2,2,2,2,2};
Vector z{3,3,3,3,3};
Vector r = x + y + z;

由于移动省略,将创建Vector类的5个对象。

关于c++ - 在重载 vector 求和中移动分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62439111/

相关文章:

c++ - 运算符重载嵌套在类中的枚举

c++ - 变量已在 .obj 中定义,但没有循环包含

c++ - 无法理解类构造函数

templates - 未知类型名称 ‘vector’

c++ - 在 C++ 中对 vector 的 vector 进行排序

c++ - 将一种数据类型的 vector 复制到相同数据类型的结构体 vector 中的有效方法是什么?

c++ - QT 5 64 位适用于 Windows 和 VS2010

c++ - 如何知道 wxFrame 何时关闭?

c++ - 请帮我找出为什么我陷入无限循环?

C++11类函数的多重定义