Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
移动构造器&;移动分配 我一直在阅读Bjarne Stroustrup(C++的创建者)的《C++程序设计语言第四版》,并一直在学习移动构造函数和移动赋值。p>_C++_Move Constructor_Move Assignment Operator - Fatal编程技术网

移动构造器&;移动分配 我一直在阅读Bjarne Stroustrup(C++的创建者)的《C++程序设计语言第四版》,并一直在学习移动构造函数和移动赋值。p>

移动构造器&;移动分配 我一直在阅读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

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

我没有得到任何错误,并且已经看过很多例子,但是我不能确认它对于我的特定类是正确的。有经验的C++请看我的代码和评论,如果它是正确的?< /P> 编辑:有关构造函数和析构函数,请参见4。

谢谢你抽出时间

注:欢迎提供任何有用的提示或修改

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