【问题标题】:Move Constructor & Move Assignment移动构造函数和移动赋值
【发布时间】:2017-09-23 13:18:40
【问题描述】:

我一直在阅读 Bjarne Stroustrup(c++ 的创建者)的《C++ 编程语言第 4 版》一书,并且一直在学习移动构造函数和移动赋值。

在类向量的书中(见下面的标题1)他展示了如何实现移动构造函数(见下面的2)并说移动赋值是以类似的方式实现的,但没有展示如何实现。我自己实现了移动任务(见下面的 3),一切似乎都运行良好,但是,我不确定我是否正确实现了它。

我没有收到任何错误,并且查看了许多示例,但我无法确认它对于我的特定课程是否正确。有 c++ 经验的人可以看看我的代码并评论是否正确?

编辑:构造函数和析构函数也请参见 4。

感谢您的宝贵时间。

P.S: 欢迎任何有用的提示或修改

1) 类头文件:

#ifndef VECTOR_H
#define VECTOR_H

#include <cstdlib>
#include <iostream>
#include <stdexcept>

using namespace std;

template<typename T>
class Vector {

public:
    // constructors
    Vector(int s);
    Vector(std::initializer_list<T>);

    // destructor
    ~Vector();

    // copy constructor and copy assignment
    Vector(Vector&);
    Vector<T>& operator=(Vector&);

    // move constructor and move assignment
    Vector(Vector&&);
    Vector<T>& operator=(Vector&&);

    // operators
    T& operator[](int);
    const T& operator[](int) const; // the second const means that this function cannot change the state of the class
                                    // we define operator[] the second time for vectors containing constant members;
    // accessors
    int getSize();


private:
    int size;
    T* elements;

};

#endif /* VECTOR_H */

2) 移动构造函数(实现方式与book相同):

// move constructor 
template<typename T>
Vector<T>::Vector(Vector&& moveme) : size{moveme.size}, elements{moveme.elements}
{
    moveme.elements = nullptr;
    moveme.size = 0;
}

3) 移动分配(不确定是否正确):

// move assignment
template<typename T>
Vector<T>& Vector<T>::operator=(Vector&& moveme) 
{
    delete[] elements; // delete old values
    elements = moveme.elements;
    size = moveme.size;
    moveme.elements = nullptr;
    moveme.size = 0;
    return *this;
}

4) 构造函数和析构函数:

#include <array>

#include "Vector.h"

// constructors
template<typename T>
Vector<T>::Vector(int s) {    
    if(s<0) throw length_error{"Vector::Vector(int s)"};
    // TODO: use Negative_size{} after learning how to write custom exceptions
    this->size = s;
    this->elements = new T[s];
}

template<typename T>
Vector<T>::Vector(std::initializer_list<T> list) : size(list.size()), 
        elements(new T[list.size()]) 
{
    copy(list.begin(), list.end(), elements);
}

// destructor
template<typename T>
Vector<T>::~Vector()
{
    delete[] this->elements;
}

【问题讨论】:

  • 移动分配似乎是合理的,除了将模板放入 cpp 文件使它们只能在该 cpp 文件中使用。见Why can templates only be implemented in the header file?
  • @hammeramr 将模板代码放在 *.cpp 文件中会让那些期望它可编译的人感到困惑,也会让一些可能自动尝试实际编译它的 IDE 或构建系统感到困惑,即毫无意义。
  • @hammeramr std::move != move semantics。您有移动语义,其中右值可以移动(使用移动构造函数)而不是复制。 std::move 只是为非右值类型启用移动语义(如使用移动构造函数)的工具。
  • @hammeramr 带有std::move 的那个。就像使用 const&amp; 例如 int 作为函数的参数一样。从性能的角度来看,这并不重要,因为int 非常小,可以在寄存器中传递。移动它也是一样。使用你更喜欢的那个 - 我不使用它,因为它的输入更少:P
  • @hammeramr 不,我对child_vector 的意思是,如果你在班上有一个叫那个的成员。但你没有,所以忘记这一点。此外,如果您没有重载移动 ctors/assignments,是否真的没有返回值优化?

标签: c++ move-constructor move-assignment-operator


【解决方案1】:

由于这个问题在 cmets 中得到了回答,我想我会听从 meta 的建议:Question with no answers, but issue solved in the comments (or extended in chat) 并写一个简短的社区 Wiki 来关闭并回答这个问题。

我还将添加来自参与 cmets 讨论的其他用户的有用的附加信息和提示。

Bo Presson 回答并提供有关模板放置的更多信息:

移动分配似乎是合理的,除了将模板放入 cpp 文件使它们只能在该 cpp 文件中使用。看 Why can templates only be implemented in the header file?

Rakete1111 澄清我对移动语义的误解:

std::move != 移动语义。你有移动语义,其中右值 可以移动(使用移动构造函数)而不是复制。标准::移动 只是一种启用移动语义的工具(例如使用移动 构造函数)用于不是右值的类型。

kim366Jive Dadson 提出回报优化问题,我回答:

...另外,如果您不这样做,是否真的没有返回值优化 有重载的移动 ctors/assignments 吗? -kim366

似乎是这样,在示例中(参见下面的函数)他说z = x + y + z 将复制返回结果两次“如果向量很大,比如说, 10,000 个双打,那可能会很尴尬。”但是“鉴于 定义,编译器会选择move构造函数来实现 返回值的转移......”他发明了 c++ 所以我只是采取 他的话:)。 Vector operator+(const Vector& a, const Vector& b) { if (a.size()!=b.size()) throw Vector_size_mismatch{}; Vector res(a.size()); for (int i=0; i!=a.size(); ++i) res[i]=a[i]+b[i]; return res; } - 锤子

(示例来自本书:“C++ 编程语言第 4 版” 通过 Bjarne Stroustrup)

另请参阅 What is the copy-and-swap idiom? -杰夫·达森

希望人们觉得这很有用,并感谢那些参与的人。

【讨论】:

    猜你喜欢
    • 2020-03-22
    • 2021-05-31
    • 2016-05-19
    • 2015-03-03
    • 2017-05-15
    • 2016-09-13
    • 2013-11-18
    • 2015-07-10
    • 2019-09-29
    相关资源
    最近更新 更多