简体   繁体   English

移动构造函数如何在C ++中工作?

[英]How move constructor works in C++?

I have read many articles about move constructor (even on stack) but i didn't find anywhere an exact explanation about how this works (how is transfer pointer to a temporary object and saved if this temporary variable and its address will be destroy when meet ")" ). 我已经阅读了很多关于移动构造函数的文章(甚至在堆栈上),但是我没有找到关于它是如何工作的确切解释(如果转移指针指向临时对象并且如果此临时变量及其地址在遇到时将被销毁则保存“)”)。

Here is a simple example 这是一个简单的例子

#include <iostream>
#include <vector>
using namespace std;
class boVector {
private:
    int size;
public:
    boVector() {};
    boVector(const boVector& rhs) { cout << "copy Ctor." << endl; }
    boVector(boVector&& rhs) { cout << "move Ctor." << endl; }
};

void foo(boVector v) {}
boVector createBoVector() { return boVector(); }

int main()
{
    //copy
    boVector reausable = createBoVector();
    foo(reausable);
    //move
    foo(std::move(createBoVector()));
    return 0;
}

All say that a move Ctor is a shallow copy copy or just a pointer assignment. 所有人都说移动Ctor是浅拷贝副本或只是一个指针赋值。 But how can i initiate my object with a pointer to a temporary object (when this object will be destroy my object will point to an unknown address and this is not valid from my point of view). 但是,如何使用指向临时对象的指针启动我的对象(当此对象将被破坏时,我的对象将指向一个未知地址,从我的角度来看这是无效的)。

Is not right to initiate a variable with a pointer address that will no longer exist after he meet ")". 用指针地址启动变量是不对的,在满足“)”后它将不再存在。

Please if can somebody explain me how looks this temporary variable in memory and how is possible to assigned the address of temporary object to my current one and this operation to be a valid one. 请问是否可以有人解释我如何在内存中查找此临时变量以及如何将临时对象的地址分配给我当前的一个并且此操作是有效的。

A "move constructor" is nothing magical - it is a constructor that takes an rvalue reference . “移动构造函数”并不神奇 - 它是一个采用右值引用的构造函数。

Rvalue references bind to temporary object, and have the "meaning" of something that's about to expire and that won't be accessed later on in the program: this enables developers to implement moves for resource-holding classes in terms of pointer swaps or similarly fast operations. Rvalue引用绑定到临时对象,并具有即将到期的某些东西的“含义”,并且稍后将无法在程序中访问:这使开发人员能够根据指针交换或类似方式实现资源保留类的移动快速操作。

Your boVector class cannot really take any advantage from move semantics, as it just stores an int and doesn't hold any resource. 你的boVector类实际上不能从移动语义中获得任何好处,因为它只存储一个int并且不包含任何资源。 Moving an int is as fast as copying one. 移动int与复制int一样快。


In the 在里面

foo(std::move(createBoVector()));

expression, std::move is redundant as createBoVector() is already an rvalue . 表达式, std::move是多余的,因为createBoVector()已经是一个右值


Consider: 考虑:

foo(createBoVector());

This will invoke boVector(boVector&&) as it's a better match than boVector(const boVector&) . 这将调用boVector(boVector&&)因为它比boVector(const boVector&)更好。

The instance created by createBoVector() will live for the full duration of the expression - this means that the rvalue reference will be pointing to a valid object for the duration of boVector(boVector&&) . createBoVector()创建的实例将在表达式的整个持续时间内生效 - 这意味着rvalue引用将在boVector(boVector&&)的持续时间内指向有效对象。

All say that a move Ctor is a shallow copy copy or just a pointer assignment. 所有人都说移动Ctor是浅拷贝副本或只是一个指针赋值。

Not all say that, as it is not true. 并非所有人都这么说,因为事实并非如此。 A move constructor is what you define it to be. 移动构造函数是您定义它的原因。 In your example, your move ctor does something else entirely. 在您的示例中,您的移动ctor完全做了其他事情。 The point of a move ctor - as opposed to a copy ctor - is that you know that the other object is about to be destroyed, so you can cannibalize, or move, its resources. 移动ctor - 与复制ctor相反 - 是你知道另一个对象即将被销毁,所以你可以蚕食或移动它的资源。

A move constructor may make a "shallow copy", although that term is colloquial rather than well-defined in C++. 移动构造函数可以制作“浅拷贝”,尽管该术语是口语而不是在C ++中定义明确。 "Just a pointer assignment" - perhaps, possibly, sometimes. “只是一个指针分配” - 也许,有时可能。

But how can i initiate my object with a pointer to a temporary object (when this object will be destroy my object will point to an unknown address and this is not valid from my point of view). 但是,如何使用指向临时对象的指针启动我的对象(当此对象将被破坏时,我的对象将指向一个未知地址,从我的角度来看这是无效的)。

You don't (usually) initialize an object of type T with a pointer of type T* , per se. 您(通常)不会使用类型为T*的指针初始化类型为T的对象。 You can assign my_t = *my_t_ptr , or if you know you can "cannibalize" the T which my_t_ptr is pointing to, since it will soon be deleted, then you can assign my_t = std::move(*my_t_ptr) . 您可以指定my_t = *my_t_ptr ,或者如果您知道可以“蚕食” my_t_ptr指向的T ,因为它很快就会被删除,那么您可以指定my_t = std::move(*my_t_ptr)

Can you give me a more relevant example [of a meaningful difference between a move constructor and a copy constructor]...? 你能给我一个更相关的例子[移动构造函数和复制构造函数之间有意义的区别] ......?

The "classical" example is when your T is constructed by allocating some space on the heap. “经典”示例是通过在堆上分配一些空间来构造T When you copy-construct one T from another, you have no choice but to allocate a second stretch of memory; 当你从另一个T复制构造一个T时,你别无选择,只能分配第二段内存; when you move-construct a T , you can :1. 当你移动构造一个T ,你可以:1。 copy the pointer from the existing T to the T under construction. 将指针从现有T复制到正在构建的T 2. set the existing T 's member pointer to nullptr . 2.将现有T的成员指针设置为nullptr In this case you only ever use one T 's worth of stack space. 在这种情况下,您只使用一个T的堆栈空间。

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

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