我最近做的项目用到了C++11的多线程库,其中一个类A中有一个类B的成员,而类B的成员中使用到了std::mutex互斥锁,这个互斥锁在B中使用没有任何问题,但是当类B成为一个类A的成员之后,就出现了问题,

1>e:\workqt\spotdetect\detectviewer.cpp(5): error C2280: “Detector::Detector(const Detector &): 尝试引用已删除的函数
1>e:\workqt\spotdetect\detector.h(97): note: 编译器已在此处生成“Detector::Detector”
1>e:\workqt\spotdetect\detector.h(97): note: “Detector::Detector(const Detector &): 因为 数据成员 调用已删除或不可访问的函数“std::mutex::mutex(const std::mutex &)”,所以已隐式删除函数 (编译源文件 detectviewer.cpp)
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\mutex(91): note: “std::mutex::mutex(const std::mutex &): 已显式删除函数 (编译源文件 detectviewer.cpp)

对这个问题一度很迷茫,最后查了半天,是因为包含关系导致的,类A中有一个类B的成员,类B中有一个互斥锁,而查看std::mutex源代码,mutex的拷贝构造函数是被delete的,不允许拷贝构造,然而在类A的构造函数中,调用类B的构造函数,然后将其赋值到类A的对应类B这个成员变量下,这个赋值,就会调用类B的赋值运算符,而我没有去特殊定义,这样就会调用编译器生成的默认拷贝赋值运算符,将B中的数据逐bit拷贝,而拷贝B中的mutex的时候,就会报编译错误error C2280。

所以根据这样的情况,总结几种解决方案:
1.在类包含类的情况下,不要在被包含的类中使用std::mutex。
2.重写类B的赋值运算符,拷贝除了mutex以外的其他数据成员,重新构造一个新的mutex给拷贝过去的对象使用。
3.类B中的mutex可以改为一个指向mutex的指针或者shared_ptr,这样触发默认赋值运算符的时候,拷贝的就是指针,指针本身可以拷贝,也可解决问题。

我最近做的项目用到了C++11的多线程库,其中一个类A中有一个类B的成员,而类B的成员中使用到了std::mutex互斥锁,这个互斥锁在B中使用没有任何问题,但是当类B成为一个类A的成员之后,就出现了问题,1>e:\workqt\spotdetect\detectviewer.cpp(5): error C2280: “Detector::Detector(const Detector &)”: 尝试引用已删除的函数1>e:\workqt\spotdetect\detector.h( 结果在 A * a = new A() 时提示错误 “error C2280: “尝试引用删除函数” 结果发现问题所在:在 className objectName 中,其析构函数没有 public 造成的。 class classNa...
前面两讲《C++11 并发指南(std::thread 详解) 》,《C++11 并发指南三(std::mutex 详解) 》分别介绍了 std::thread 和 std::mutex,相信读者对 C++11 中的多线程编程有了一个最基本的认识,本文将介绍 C++11 标准中 头文件里面的类和相关函数。 头文件中包含了以下几个类和函数: Providers 类:std::promise, std::package_task Futures 类:std::future, shared_future. Providers 函数std::asyn
ninja-mutex是一个易于使用的php互斥量实现。 它支持不同的适配器(flock,memcache,mysql,redis等),因此您可以根据需要进行设置。 所有适配器(如果设置正确)都可以在多服务器环境中使用-换句话说,锁在Web服务器之间共享。 首先,您需要选择一个适配器并正确设置它。 例如,如果首先选择flock实现,则需要设置NFS文件系统并将其安装在Web服务器上。 在此示例中,我们将选择内存缓存适配器: require 'vendor/autoload.php' ; use NinjaMutex \ Lock \ MemcacheLock ; use NinjaMutex \ Mutex ; $ memcache = new Memcache (); $ memcache -> connect ( '127.0.0.1' , 11211 ); $ lock = new MemcacheLock ( $ memcache ); $ mutex = new Mutex ( 'very-critical-stuff' , $ lock ) 在使用自己编写的类实例化c++linklist,结果编译器报了以下错误 错误 C2280 “LList::LList(const LList &)”: 尝试引用删除函数 l 从错误的内容看,似乎是自己的类的赋值构造函数尝试调用却发现其已被删除。 一般而言,对象的赋值构造函数如果开发者没有提供,则编译器会生成默认的赋值构造函数。然... 这个类是一个多生产者、多消费者队列。 它同时提供阻塞和非阻塞消费,而生产总是阻塞。 容量是动态调整的。 实现基于std::queue ,使用std::mutexstd::condition_variable实现线程安全。 可以使用右值引用调用Produce(T&& item)函数。 Consume(T& item)函数立即返回一个布尔值,表示成功。 ConsumeSync(T& item)方法将阻塞调用线程,直到它可以从队列中取出一个项目。 Finish方法停止所有等待的消费者 (ConsumeSync),并使它们返回 false。 SafeQueue<MyType> queue; // insert elements queue.Produce(std::move(var1)); queue.Produce(std::move(var2)); 非阻塞消费 错误 C2280 “(类名)::operator =(const (类名) &)”: 尝试引用删除函数 F:\vs2015\VC\include\xutility 2581 从错误的内容看,似乎是自己的类的赋值构造函数尝试调用却发现其已被删除。 在翻阅了资料后发现,erase方法会在将对象删除后,将所有该对象之后的对象向前移动。此时会调用该对象的赋值构造函数
std::mutexstd::lock_guard 是 C++ 中的互斥锁类型。 std::mutex 是一个互斥锁类型,它可以用来保护临界区。当一个线程获取互斥锁时,其他线程将不能访问被保护的临界区。 std::lock_guard 是一个 RAII 类型,它用于简化互斥锁的使用。当 std::lock_guard 对象创建时,它会获取一个互斥锁,并在它的生命周期结束时释放该互斥锁。 这两个类型常常被用来保护共享数据,避免竞争条件和其他线程间同步问题。 使用 std::mutex 的例子: std::mutex mutex; void foo() mutex.lock(); // 访问共享数据 mutex.unlock(); 使用 std::lock_guard 的例子: std::mutex mutex; void foo() std::lock_guard<std::mutex> lock(mutex); // 访问共享数据 std::lock_guard 比 std::mutex 更加方便,因为它会自动在生命周期结束时释放互斥锁,避免忘记调用 unlock() 导致死锁的问题。