type
Post
status
Published
slug
2023/04/18/Why-is-it-necessary-to-prohibit-the-default-copy-when-implementing-the-Thread-class-in-c++11
summary
tags
思考
开发
category
学习思考
icon
password
new update day
Property
Oct 22, 2023 01:31 PM
created days
Last edited time
Oct 22, 2023 01:31 PM

为什么需要禁止默认拷贝

线程是一个独立的执行流

在C++中,线程是一个独立的执行流,可以运行在不同的CPU核心上,它可以读写共享内存数据。当多个线程同时访问同一块内存时,可能会出现竞争条件(即每个线程尝试更改变量或其他资源,并且最终结果取决于执行的顺序),这可能导致数据损坏或未定义行为。

线程资源具有独占性

由于线程资源具有独占性,一个线程只能拥有对其所执行的代码和数据的访问权。
如果我们允许线程对象的默认复制构造函数和赋值运算符,就会导致多个线程引用同一个资源,这可能会导致数据竞争或死锁等问题。例如:
#include <thread> class Thread { public: void thread_func() { // 线程函数 } private: std::thread m_thread; }; void foo() { Thread t1; // 创建线程t1 t1 = Thread(); // 复制线程,t1和t2都指向同一个线程对象 Thread t2 = t1; // ... }
在这个例子中,我们创建了线程t1,然后将线程复制给t2,这导致两个线程引用同一个线程资源,可能导致数据竞争或死锁等问题。
因此,在实现Thread类时,我们需要禁止默认拷贝,以确保每个线程对象都唯一地拥有对其所执行的代码和数据的访问权。可以通过将复制构造函数和赋值运算符声明为private并不实现它们的方式来禁止默认拷贝。这样,我们就只能使用移动语义在线程对象之间转移资源。

怎么禁止默认拷贝

可以通过将复制构造函数和赋值运算符声明为private并不实现它们的方式来禁止默认拷贝。例如:
class Thread { public: // 线程函数 void thread_func() { // ... } // 构造函数 Thread() { // ... } // 移动构造函数 Thread(Thread&& other) { // ... } // 移动赋值运算符 Thread& operator=(Thread&& other) { // ... return *this; } private: Thread(const Thread&) = delete; // 禁止默认拷贝 Thread(const Thread&&) = delete; Thread& operator=(const Thread&) = delete; // 线程对象 std::thread m_thread; };
在这个例子中,我们将复制构造函数和赋值运算符声明为private并且不实现它们,以禁止默认拷贝。同时,我们提供了移动构造函数和移动赋值运算符,支持线程对象的移动语义。
 
欢迎加入喵星计算机技术研究院,原创技术文章第一时间推送。
notion image
 
C++ 中虚函数与纯虚函数在开发过程中的区别与作用C++ 删除文件最后一行的空行