类构造函数创建线程:对象与指针实例化行为差异答疑
问题分析与解决方案
嘿,我来帮你捋捋这个问题的核心原因,其实是对象生命周期和线程等待逻辑出了问题,咱们一步步拆解:
为什么栈对象t能正常执行foo()?
当你创建栈对象test t;时,它的生命周期由C++编译器自动管理——main()函数执行完毕退出前,会自动调用t的析构函数。你的析构函数里写了m_thread.join();,这会让主线程等待子线程完成foo()的执行后再继续,所以foo()的输出能正常显示出来。
为什么堆对象t1的foo()完全不执行?
你用new创建的堆对象,生命周期是由你手动控制的:
- 你没有调用
delete t1;来销毁这些堆对象,所以它们的析构函数永远不会被执行,析构里的join()也就不会触发。 - 当
main()函数返回时,进程会直接终止,操作系统会强制杀死进程内的所有线程——这时候你的子线程可能还没来得及执行到cout输出的代码,就被终止了,自然看不到任何输出。
另外,你的代码里还有一个编译错误:main()里连续两次定义了test *t1,这是C++语法不允许的,得改成不同的变量名(比如t1和t2),或者避免重复定义。
修正后的代码示例
我们只需要手动销毁堆对象,让析构函数执行join(),就能让foo()正常输出:
#include <iostream> #include <thread> using namespace std; void foo() { cout << "foo.. foo.. foo.." << endl; } class test { public: test(); ~test(); private: std::thread m_thread; }; test::test() { this->m_thread = std::thread(foo); } test::~test() { // 先检查线程是否可join,避免重复join的问题 if (m_thread.joinable()) { m_thread.join(); } } int main() { test t; // foo()函数执行 test *t1 = new test; delete t1; // 手动销毁堆对象,触发析构和join test *t2 = new test(); delete t2; // 同样手动销毁 return 0; }
额外建议:使用智能指针避免内存泄漏
如果你不想手动管理delete,可以用std::unique_ptr或者std::shared_ptr来自动管理堆对象的生命周期,这样就不用担心忘记销毁对象的问题了:
#include <memory> // 记得包含头文件 int main() { test t; auto t1 = make_unique<test>(); // 自动销毁 auto t2 = make_shared<test>(); // 自动销毁 return 0; }
内容的提问来源于stack exchange,提问作者Surya Pratap Singh
相关产品推荐
相关产品推荐

