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

push back an object which has only move constructor to a vector

这是一个比较笼统的问题。在这个 post Where does a std::vector allocate its memory? 中它说 vector 默认在堆中分配它的元素。在 C++11 中,有移动语义并且 vector 支持它。如果我有一个只有 move 构造函数的对象,并且我已经在堆栈中声明了这个对象,现在我想 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?
}

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

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

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

所以是的,你可以将一个只能移动的类型推入一个向量,但是不行,它不会以某种方式神奇地将一块堆栈 space 转换成一块堆 space。它只是在 vector 中创建一个新对象,并将堆栈上对象的 contents 移入其中。内容如何移动(即移动到底是什么)由每个对象决定——这就是移动构造函数所做的。

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

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();

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

调用移动构造函数实际上意味着:"copy this object, and by the way you can cannibalize any data structure already allocated for this object because I will not use it anymore".