基于下方C++代码,myClass1对象及其成员myClass2是否随内存移动至新线程?
首先先修正下你代码里的几个语法小问题(方便后续分析):
#include <iostream> #include <thread> #include <string> using namespace std; class myClass2{ public : string str; myClass2(string str){ this->str = str; } // 修正类名拼写和this访问方式 }; class myClass1{ public: myClass2 obj; myClass1(myClass2 * obj) { this->obj = *obj; } // 修正this访问方式 thread spawn() { return std::thread([this] { this->Run(); }); } void Run() { cout << "new thread" << endl; } }; int main(){ myClass2 temp("test"); myClass1 object(&temp); auto t = object.spawn(); t.join(); return 0; }
回到你的核心问题:myClass1对象及其成员myClass2绝对不会像std::move()那样把自身内存转移到新创建的线程中,原因如下:
Lambda捕获[this]只是获取对象指针,而非转移内存
你在spawn函数里创建线程时,lambda捕获的this是当前myClass1对象的指针。新线程只是持有这个指针,它会在新线程上下文里通过指针访问原myClass1对象的成员,原对象的内存依然留在创建它的线程(这里是main线程的栈上),没有任何内存转移操作。myClass2成员是值拷贝而来,不存在资源转移
myClass1的构造函数里,this->obj = *obj;是把传入的myClass2对象做了一次值拷贝,也就是说myClass1的obj成员是一个独立的拷贝,它的内存属于myClass1对象的一部分。新线程访问的是这个拷贝,但同样没有把这个拷贝的内存转移到新线程空间的操作——内存依然属于原myClass1对象所在的内存区域。整个代码中没有触发std::move的场景
std::move的核心是将对象的资源所有权转移(比如把string的底层缓冲区从一个对象移到另一个),但你的代码里既没有调用std::move,也没有任何会触发移动语义的操作(比如返回局部对象、用std::move构造新对象等),所以完全不存在“内存移动”的行为。
额外注意事项
如果main线程中的myClass1对象(比如示例里的object)在新线程结束前被销毁(比如main函数提前退出,或者object出了作用域),新线程再通过this指针访问对象成员就会触发未定义行为,因为原对象的内存已经被释放了。
内容的提问来源于stack exchange,提问作者Amir Rasti

