c++ - 移动构造函数和移动赋值

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

我一直在阅读 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.

kim366Jive 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/

相关文章:

C++ 关系运算符生成器

c++ - 我看到的所有基于 std::move() 的 std::swap() 实现都是错误的吗?

c++ - 通过 destruct+move 构造的 move 分配安全吗?

c++11 - 新的现代 C++ 容器中的分配器传播策略

c++ - 编译器不会使用复制分配来代替移动?

c++ - 编写一个算法以返回整数的质数,例如,如果您的输入是 10,则输出是包含元素 2 和 5 的列表 a

c++ - boost 属性树 : Remove a node

c++ - 对 CString 中包含的值进行舍入

c++ - C++:有关使用Stroustrup示例的移动构造函数/赋值的问题

c++ - 在重载 vector 求和中移动分配