移动构造器&;移动分配 我一直在阅读Bjarne Stroustrup(C++的创建者)的《C++程序设计语言第四版》,并一直在学习移动构造函数和移动赋值。p>
在关于类向量的书中(见下文标题1),他展示了如何实现move构造函数(见下文2),并说move赋值是以类似的方式实现的,但没有展示如何实现。我自己执行了移动任务(见下面的3),一切似乎都很好,但是,我不确定我是否正确执行了它 我没有得到任何错误,并且已经看过很多例子,但是我不能确认它对于我的特定类是正确的。有经验的C++请看我的代码和评论,如果它是正确的?< /P> 编辑:有关构造函数和析构函数,请参见4。 谢谢你抽出时间 注:欢迎提供任何有用的提示或修改 1) 类头文件:移动构造器&;移动分配 我一直在阅读Bjarne Stroustrup(C++的创建者)的《C++程序设计语言第四版》,并一直在学习移动构造函数和移动赋值。p>,c++,move-constructor,move-assignment-operator,C++,Move Constructor,Move Assignment Operator,在关于类向量的书中(见下文标题1),他展示了如何实现move构造函数(见下文2),并说move赋值是以类似的方式实现的,但没有展示如何实现。我自己执行了移动任务(见下面的3),一切似乎都很好,但是,我不确定我是否正确执行了它 我没有得到任何错误,并且已经看过很多例子,但是我不能确认它对于我的特定类是正确的。有经验的C++请看我的代码和评论,如果它是正确的?< /P> 编辑:有关构造函数和析构函数,请参见4。 谢谢你抽出时间 注:欢迎提供任何有用的提示或修改 1) 类头文件: #ifndef VE
#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 */
#ifndef向量
#定义向量
#包括
#包括
#包括
使用名称空间std;
模板
类向量{
公众:
//建设者
向量(int-s);
向量(std::初始值设定项列表);
//析构函数
~Vector();
//复制构造函数和复制赋值
向量(向量&);
向量和运算符=(向量和);
//移动构造函数和移动赋值
向量(向量&&);
向量和运算符=(向量和);
//操作员
T&operator[](国际);
常量T&运算符[](int)const;//第二个常量表示此函数无法更改类的状态
//对于包含常量成员的向量,我们第二次定义了算子[];
//访问者
int getSize();
私人:
整数大小;
T*元素;
};
#endif/*向量*/
2) 移动构造函数(以与book相同的方式实现):
//移动构造函数
模板
Vector::Vector(Vector&&moveme):大小{moveme.size},元素{moveme.elements}
{
moveme.elements=nullptr;
moveme.size=0;
}
3) 移动分配(不确定是否正确):
//移动分配
模板
向量和向量::运算符=(向量和移动对象)
{
delete[]元素;//删除旧值
元素=moveme.elements;
size=moveme.size;
moveme.elements=nullptr;
moveme.size=0;
归还*这个;
}
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;
}
#包括
#包括“Vector.h”
//建设者
模板
向量::向量(int s){
如果(ssize=s;
此->元素=新的T[s];
}
模板
Vector::Vector(std::initializer\u list list):大小(list.size()),
元素(新的T[list.size()])
{
复制(list.begin()、list.end()、元素);
}
//析构函数
模板
向量::~Vector()
{
删除[]此->元素;
}
既然这个问题在评论中得到了回答,我想我应该遵循meta的建议:写一个简短的社区Wiki来结束并回答这个问题
我还将添加其他用户在评论中加入讨论的有用信息和提示
回答并提供有关模板放置的其他信息:
移动分配似乎是合理的,除了将模板放入
cpp文件使它们只能在该cpp文件中使用。请参阅
澄清我对移动语义的误解:
std::move!=移动语义。您有移动语义,其中r值
可以移动(使用移动构造函数)而不是复制。std::move
只是一个启用移动语义的工具(如使用移动
构造函数),用于非右值的类型
提出回报优化问题,我回答:
…此外,如果您不这样做,是否真的没有返回值优化
你有过超负荷的任务吗?-kim366
似乎是这样,在示例中(见下面的函数),他说z=x+
y+z将复制两次返回结果“如果向量较大,例如,
10000双,那可能会很尴尬
定义时,编译器将选择要实现的移动构造函数
返回价值的转移……“他发明C++,所以我只接受
他的话是:)<代码>向量运算符+(常量向量&a,常量向量&
b) {如果(a.size()!=b.size())抛出向量大小不匹配{};向量
res(a.size());for(inti=0;i!=a.size();++i)res[i]=a[i]+b[i];
返回res;}
-hammeramr
(从C++中的例子):《C++程序设计语言第四版》 作者:比亚恩·斯特罗斯图普)
另见 -吉夫·达森希望大家觉得这很有用,并感谢那些参与的人 移动分配似乎是合理的,只是将模板放入cpp文件中会使它们仅在该cpp文件中可用。请参阅@hammeramr将模板代码放入*.cpp文件会让那些可能希望它可编译的人感到困惑,也会让一些IDE或构建系统感到困惑,因为它们可能会自动尝试实际编译它,这是毫无意义的。@hammeramr
std::move!=移动语义
。您有移动语义,其中可以移动右值(使用移动构造函数)而不是复制右值std::move
只是一种工具,用于为非右值的类型启用移动语义(如使用移动构造函数)。@hammeramr是带有std::move
的类型。就像使用const&
作为函数的参数一样,例如int
。从性能角度看,这无关紧要,因为int
非常小,可以在寄存器中传递。移动它也是一样的。使用你更喜欢的一个-我不使用它,因为它不太容易打字:P@hammeramr不,我所说的子向量的意思是,如果你班上有一个叫它的成员。但你没有,所以忘了吧。另外,如果您没有重载的move-ctors/assignment,是否真的没有返回值优化?
// 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;
}
#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;
}