将只有移动构造函数的对象推回到向量

时间:2015-05-13 16:39:34

标签: c++ c++11 vector move

这是一个相当普遍的问题。在这篇文章Where does a std::vector allocate its memory?中,它表示默认情况下vector在堆中分配其元素。在C ++ 11中,有移动语义,vector支持这一点。如果我有一个只有移动构造函数的对象,并且我已经在堆栈中声明了这个对象,现在我想将push_back这个对象变成vector,那么这个对象仍被推回到堆?

示例可能是将声明为std::thread t1(someFunc)的堆栈推回vector,如下所示

int main(){
      std::thread t1(someFunc);
      std::vector<std::thread> threads;
      threads.push_back(t1); // is the one being pushed back in the heap
                             // or in the stack? Is the answer generally
                             // true for objects which have only move
                             // constructors?
}

3 个答案:

答案 0 :(得分:7)

存储在矢量中的实例将始终与您推入的实例不同,即使它已被移动。移动对象只会调用移动构造函数而不是向量中创建的相应对象的复制构造函数。

所以是的,你可以将一个可移动的类型推送到一个向量中,但不是,它不会以某种方式神奇地将一堆堆栈空间转换为一堆堆空间。它只是在向量中创建一个新对象,并将堆栈中对象的内容移入其中。内容如何被移动(即移动是什么,确切地说)取决于每个对象来决定 - 这就是移动构造器所做的事情。

执行此操作的语法可能如下所示:

std::vector<std::thread> threads;
std::thread t([]() { /* do something */ });

// You need `std::move` here to force the object to be treated as
// an r-value and get moved instead of trying to be copied.
threads.push_back(std::move(t));

// At this point `t` still exists (until the end of scope), but
// its contents (while valid) are indeterminate. It does not refer
// to the running thread any more.

threads.back().join();

答案 1 :(得分:3)

移动对象将状态从一个对象转移到另一个对象;这两个对象是分开的,位于不同的位置,之后在相同的位置保持独立的对象。

所以问题的答案是肯定的:向量中的对象在堆上,无论用于初始化它的对象驻留在哪里。

答案 2 :(得分:0)

在C ++ 11中调用移动构造函数并不能实际移动任何东西。它只是一种管理对象生命周期和所有权的机制。

调用移动构造函数实际上意味着:&#34;复制此对象,并且通过这种方式可以蚕食已为此对象分配的任何数据结构,因为我将不再使用它&#34;。