【发布时间】: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&例如int作为函数的参数一样。从性能的角度来看,这并不重要,因为int非常小,可以在寄存器中传递。移动它也是一样。使用你更喜欢的那个 - 我不使用它,因为它的输入更少:P -
@hammeramr 不,我对
child_vector的意思是,如果你在班上有一个叫那个的成员。但你没有,所以忘记这一点。此外,如果您没有重载移动 ctors/assignments,是否真的没有返回值优化?
标签: c++ move-constructor move-assignment-operator