移动构造函数&移动作业

时间:2017-09-23 13:18:41

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

我一直在阅读Bjarne Stroustrup(c ++的创建者)的“The C ++ programing language 4th edition”一书,并且一直在学习移动构造函数和移动赋值。

在类向量的书中(参见下面的标题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)移动构造函数(以与书相同的方式实现):

// 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;
}

1 个答案:

答案 0 :(得分:1)

由于在评论中回答了这个问题,我认为我应该遵循meta Question with no answers, but issue solved in the comments (or extended in chat)的建议,写一个简短的社区Wiki来关闭并回答这个问题。

我还将添加来自评论中加入讨论的其他用户的有用的其他信息和提示。

Bo Presson回答并提供有关模板展示位置的其他信息:

  

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

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

  

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

kim366使用Jive Dadson提出返回优化问题,我回答:

  

...另外,如果你不这样做,真的没有回报 - 价值优化   有超负荷移动ctors /作业? -kim366

     

看起来如此,在示例中(参见下面的函数),他说z = x + y + z将复制两次返回结果&#34;如果Vector很大,比方说,   10,000个双打,这可能令人尴尬。&#34;但是,考虑到这一点   定义时,编译器会选择移动构造函数来实现   转移价值......&#34;他发明了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; } - hammeramr

     

(例子来自书:&#34; C ++编程语言第4版&#34;   作者:Bjarne Stroustrup

     

另见   What is the copy-and-swap idiom?   -Jive Dadson

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