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

时间:2018-01-17 13:40:16

标签: c++ c++11 constructor move-semantics move-constructor

我已经阅读了许多关于移动构造函数的文章(甚至在堆栈上),但我没有找到关于它如何工作的确切解释(如果转移指针指向临时对象并且如果此临时变量及其地址将是见面时会破坏“)”)。

这是一个简单的例子

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

所有人都说移动Ctor是浅拷贝副本或只是指针分配。但是我如何使用指向临时对象的指针启动我的对象(当此对象将被破坏时,我的对象将指向一个未知的地址,从我的角度来看这是无效的。)

使用指针地址启动变量是不对的,该变量在遇到“)”之后将不再存在。

请问有人可以解释我如何在内存中查找这个临时变量,以及如何将临时对象的地址分配给我当前的一个,并且此操作是有效的。

2 个答案:

答案 0 :(得分:10)

“移动构造函数”并不神奇 - 它是一个构造函数,它采用右值引用

Rvalue引用绑定到临时对象,并具有即将到期的某些内容的“含义”,以后不会在程序中访问:这使开发人员能够实现资源移动 - 在指针交换或类似的快速操作方面保留类。

你的boVector类无法从移动语义中获得任何好处,因为它只存储int并且不包含任何资源。移动int与复制一个一样快。

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

表达式,std::move是多余的,因为createBoVector()已经是 rvalue

考虑:

foo(createBoVector());

这将调用boVector(boVector&&),因为它比boVector(const boVector&)更好。

createBoVector()创建的实例将在表达式的整个持续时间内生效 - 这意味着右值引用将在{{1}的持续时间内指向有效对象}。

答案 1 :(得分:2)

  

所有人都说移动Ctor是浅拷贝副本或只是指针分配。

并非所有人都这么说,因为事实并非如此。移动构造函数是您定义它的原因。在您的示例中,您的移动ctor完全做了其他事情。移动ctor - 与复制ctor相反 - 是你知道另一个对象即将被销毁,所以你可以蚕食或移动它的资源。

移动构造函数可以制作一个“浅拷贝”,尽管该术语是口语而不是在C ++中定义良好。 “只是一个指针分配” - 也许,可能,有时候。

  

但是如何使用指向临时对象的指针启动我的对象(当此对象将被破坏时,我的对象将指向一个未知地址,从我的角度来看这是无效的。)

您(通常)不会使用类型为T的指针初始化类型为T*的对象。您可以指定my_t = *my_t_ptr,或者如果您知道可以“蚕食”T所指向的my_t_ptr,因为它很快就会被删除,那么您可以指定my_t = std::move(*my_t_ptr)

  

你能给我一个更相关的例子[移动构造函数和复制构造函数之间有意义的区别] ......?

“经典”示例是通过在堆上分配一些空间来构造T的时候。当你从另一个复制构造一个T时,你别无选择,只能分配第二段内存;当你移动 - 构建T时,你可以:1。将指针从现有T复制到正在构建的T。 2.将现有T的成员指针设置为nullptr。在这种情况下,您只使用一个T的堆栈空间。