我一直在阅读 Bjarne Stroustrup(C++ 的创造者)所著的“C++ 编程语言第 4 版”一书,并且一直在学习移动构造函数和移动赋值。
在有关类 vector 的书中(请参阅下面的标题 1),他展示了如何实现移动构造函数(请参阅下面的 2)并说移动分配以类似的方式实现,但没有说明如何实现。我自己实现了移动分配(参见下面的 3)并且一切似乎都运行良好,但是,我不确定我是否正确实现了它。
我没有收到任何错误并查看了很多示例,但我无法确认它是否适合我的特定类(class)。有 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;
}
最佳答案
既然这个问题在评论中得到了回答,我想我会听从元的建议:Question with no answers, but issue solved in the comments (or extended in chat)并写一个简短的社区 Wiki 来结束并回答问题。
我还会在评论中添加其他参与讨论的用户提供的有用信息和提示。
Bo Presson回答并提供有关模板放置的其他信息:
The move assignment seems reasonable, except that putting templates in a cpp file makes them usable in that cpp file only. See Why can templates only be implemented in the header file?
Rakete1111澄清我对移动语义的误解:
std::move != move semantics. You have move semantics, where rvalues can be moved (using the move constructor) instead of copied. std::move is just a facility to enable move semantics (like using the move constructor) for types that are not rvalues.
kim366用 Jive Dadson 提出返回优化问题我回答:
... Also, is there really no return-value-optimization, if you don't have overloaded move ctors/assignments ? -kim366
It seems so, in the example (see function below) he says that
z = x + y + z
will copy the return result twice "If a Vector is large, say, 10,000 doubles, that could be embarrassing." But "Given that definition, the compiler will choose the move constructor to implement the transfer of the return value..." He invented c++ so ill just take his word for it :).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(Example was from the book: "The C++ programing language 4th edition" by Bjarne Stroustrup)
See also What is the copy-and-swap idiom? -Jive Dadson
希望人们觉得这有用,并感谢那些参与的人。
关于c++ - 移动构造函数和移动赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46380008/