简体   繁体   English

无法理解关于std :: move()的c ++入门

[英]failed to understand c++primer about std::move()

The book C++ Primer says C ++ Primer一书中写道

It is essential to realize that the call to move promises that we do not intend to use rr1 again except to assign to it or to destroy it. 必须认识到移动承诺,我们不打算再次使用rr1,除非分配给它或销毁它。

This is after the line: 这是在线之后:

int &&rr3 = std::move(rr1);

How to understand this sentence? 怎么理解这句话? Is there any change to rr1 after the call std::move(rr1) ? 调用std::move(rr1)后rr1有什么变化吗?

Somebody thought this problem has be solved in What is std::move(), and when should it be used? 有人认为这个问题已经解决了什么是std :: move(),什么时候应该使用? But I don't agree that.The book written "We can destroy a moved-from object and can assign a new value to it, but we cannot use the value of a moved-from object."I don't know what it means that "we cannot use the value of a moved-from object.".Is there any code can explain it? 但我不同意。书中写道“我们可以摧毁一个移动的物体,并可以为它分配一个新值,但我们不能使用移动物体的值。”我不知道它是什么意味着“我们不能使用移动对象的值。”。是否有任何代码可以解释它?

That particular code example misses the point. 那个特定的代码示例忽略了这一点。 std::move doesn't do anything to the object that it's applied to. std::move对它所应用的对象没有任何作用。 It's just a different format for a typecast, and its effect is to guide overload resolution in cases where it matters. 它只是一种不同的类型转换格式,它的作用是在重要的情况下指导重载解析。 For example: 例如:

void f(const my_type&);
void f(my_type&&);
my_type mm;
f(mm);            // calls f(const my_type&)
f(std::move(mm)); // calls f(my_type&&)

This matters because functions that take rvalue references (in this case, f(my_type&&) ) will typically do something nasty to their argument in order to make their work easier. 这很重要,因为采用右值引用的函数(在本例中为f(my_type&&) )通常会对其参数做一些讨厌的事情,以使其工作更容易。 For example, the copy constructor for std::vector makes a copy of the argument that's passed to it; 例如, std::vector的复制构造函数会生成传递给它的参数的副本; the move constructor steals the argument's internal array, leaving the argument empty. 移动构造函数窃取参数的内部数组,将参数留空。 So when you do std::vector<int> vec(std::move(other_vector)); 所以当你做std::vector<int> vec(std::move(other_vector)); you shouldn't do anything with other_vector except assign to it or destroy it, which is what the "rule" says. 除了分配或破坏它之外,你不应该对other_vector做任何事情,这就是“规则”所说的。

The problem with the code example is that it doesn't do anything with the rvalue reference, so, as you've inferred, nothing in the object has changed, and you can continue to use it. 代码示例的问题在于它对rvalue引用没有任何作用,因此,正如您所推断的那样,对象中没有任何内容发生更改,您可以继续使用它。 But that's a silly use of std::move , and a pointless example. 但这是对std::move的愚蠢使用,也是一个毫无意义的例子。

move semantics can be understood satisfactorily when the objects have dynamically allocated memory inside them. 当对象在其中动态分配内存时,可以令人满意地理解move语义。

class MemoryBlock  
{
    public:
    MemoryBlock(size_t length) : _length(length), _data(new int[length])  
    {  
    }  

    // copy constructor.  
    MemoryBlock(const MemoryBlock& other) : _length(other._length), _data(new int[other._length])  
    {   
        std::copy(other._data, other._data + _length, _data);  
    }  

    // move copy constructor.  
    MemoryBlock(MemoryBlock&& other) : _data(nullptr), _length(0)  
    {  
        // Copy the data pointer and its length from the source object.  
        _data = other._data;  
        _length = other._length;  

        // Release the data pointer from the source object.
        other._data = nullptr;  
        other._length = 0;  
    }  

    // destructor.  
    ~MemoryBlock()  
    {  
        if (_data != nullptr)  
        {  
              delete[] _data;  
        }
        _length = 0;  
    }  

    private:  
    size_t _length; // The length of the resource.  
    int* _data; // The resource.  
};

// ok, 'a' has 20 byte memory inside it.
MemoryBlock a(20); 

// we are literally transferring the memory from 'a' to 'b' by using move copy constructor.
MemoryBlock b = std::move(a); 

// so you broke the promise: "that we do not intend to use object 'a' again" after it has been moved. 
// a::_data is now null and code will break.
MemoryBlock c = a; 

//when object 'a' will go out of scope it can be destroyed properly
//this will work because the promise holds: "that object can be destroyed" after it has been moved.

//this will work, since you are copying the memory inside of 'd' to 'a' using normal copy constructor.
//so you obeyed the promise: "that we can assign to object 'a'" after it has been moved.
MemoryBlock d(30); 
MemoryBlock a = d;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM