如何使一个类的多个对象具有std::互斥
How to have multiple objects of a class with an std::mutex?
我有以下错误:
filesystem.hpp:11:7: error: use of deleted function ‘std::mutex& std::mutex::operator=(const std::mutex&)’
In file included from /usr/include/c++/6.1.1/mutex:44:0,
from includes.hpp:11,
from htmlparser.hpp:4,
from htmlparser.cpp:1:
/usr/include/c++/6.1.1/bits/std_mutex.h:98:12: note: declared here
mutex& operator=(const mutex&) = delete;
^~~~~~~~
已经有人问了一些问题(比如这个和那个)。基于这些,我尝试了以下类代码:
class Filesystem {
private:
std::string dir = getCurrentPath();
mutable std::mutex fsMut;
public:
Filesystem() {}
~Filesystem() {}
Filesystem(const Filesystem&) : fsMut() { }
//Few more functions
};
遗憾的是,这并不奏效(甚至无法改变错误)。
现在,我的代码与前面提到的问题有何不同:在private
部分的两个类中,声明Filesystem fs;
。然而,在我看来,这是完全可以的,而对于一个类,它传递给另一个类时,会返回此错误(以及如何隐式删除该类和Filesystem
的错误)
所以我不是在复制或移动类afaik,但那会出什么问题呢?我如何修改我的代码以使其工作?
编辑:
完全错误:
htmlparser.cpp: In member function ‘strSet Htmlparser::parseLinks(std::__cxx11::string, std::__cxx11::string, std::__cxx11::string)’:
htmlparser.cpp:10:39: error: use of deleted function ‘Robotsparser& Robotsparser::operator=(const Robotsparser&)’
rsmap[origUrl] = Robotsparser(origUrl);
^
In file included from htmlparser.hpp:5:0,
from htmlparser.cpp:1:
robotsparser.hpp:7:7: note: ‘Robotsparser& Robotsparser::operator=(const Robotsparser&)’ is implicitly deleted because the default definition would be ill-formed:
class Robotsparser {
^~~~~~~~~~~~
robotsparser.hpp:7:7: error: use of deleted function ‘Filesystem& Filesystem::operator=(const Filesystem&)’
In file included from robotsparser.hpp:5:0,
from htmlparser.hpp:5,
from htmlparser.cpp:1:
filesystem.hpp:11:7: note: ‘Filesystem& Filesystem::operator=(const Filesystem&)’ is implicitly deleted because the default definition would be ill-formed:
class Filesystem {
^~~~~~~~~~
filesystem.hpp:11:7: error: use of deleted function ‘std::mutex& std::mutex::operator=(const std::mutex&)’
In file included from /usr/include/c++/6.1.1/mutex:44:0,
from includes.hpp:11,
from htmlparser.hpp:4,
from htmlparser.cpp:1:
/usr/include/c++/6.1.1/bits/std_mutex.h:98:12: note: declared here
mutex& operator=(const mutex&) = delete;
^~~~~~~~
其他类别:
class Robotsparser {
private:
std::string url;
Filesystem fs;
public:
Robotsparser(std::string u) : url(u) {}
~Robotsparser() {}
};
class A {
private:
std::mutex crawlMut;
Filesystem fs;
public:
A(std::string);
};
类A
是在Makefile的早期编译的,这可能解释了它在类Robotsparser
中给出错误的原因。
您的错误意味着有一个赋值操作试图在某个地方发生。。。
在Filesystem
类中,编译器没有抱怨复制构造函数:
Filesystem(const Filesystem&) : fsMut() {} //because there is no copying of fsMut here
但是,编译器会为您生成一个复制赋值运算符,因为您没有定义一个。在编译器生成的一个中,它调用每个成员的复制赋值运算符。
我认为你的意图是:你应该定义所有的复制/移动赋值操作符(和构造函数),并确保你不会试图复制/移动任何实例所拥有的互斥体。
Filesystem(const Filesystem& f2)
{
std::lock_guard<std::mutex> lk2(f2.fsMut);
/*do your stuff but do not copy f2.fsMut*/
}
Filesystem(Filesystem&& f2)
{
std::lock_guard<std::mutex> lk2(f2.fsMut);
/*do your stuff but do not move f2.fsMut*/
}
Filesystem& operator = (const Filesystem&)
{
std::lock(this->fsMut, f2.fsMut);
std::lock_guard<std::mutex> lk1(this->fsMut, std::adopt_lock);
std::lock_guard<std::mutex> lk2(f2.fsMut, std::adopt_lock);
//do your stuff but do not copy fsMut
return *this;
}
Filesystem& operator = (Filesystem&& f2)
{
std::lock(this->fsMut, f2.fsMut);
std::lock_guard<std::mutex> lk1(this->fsMut, std::adopt_lock);
std::lock_guard<std::mutex> lk2(f2.fsMut, std::adopt_lock);
//do your stuff but do not move fsMut
return *this;
}
完整图示如下:http://coliru.stacked-crooked.com/a/75d03fd564f8b570另外,考虑在两个互斥体上使用lock_guard
,在复制/移动分配运算符中使用std::lock
来锁定两个互斥。
尽管我对你的意图仍持保留意见,但我看到了一份会员声明,内容如下:
mutable std::mutex fsMut;
mutable
的使用是从const
成员函数中修改成员;这里通常是为了能够从CCD_ 11成员函数锁定/解锁互斥。
错误的第一位表示什么?
htmlparser.cpp: In member function ‘strSet Htmlparser::parseLinks(std::__cxx11::string, std::__cxx11::string, std::__cxx11::string)’:
htmlparser.cpp:10:39: error: use of deleted function ‘Robotsparser& Robotsparser::operator=(const Robotsparser&)’
rsmap[origUrl] = Robotsparser(origUrl);
它说在Htmlparser::parseLinks
中,在这条线上
rsmap[origUrl] = Robotsparser(origUrl);
您正在使用一个不存在的副本分配运算符。
它不存在的原因是编译器没有为您生成它,因为它不能,因为您类的mutex
成员不可复制。
然而,您真正的问题是,为什么编译器首先尝试使用这个:
所以我没有复制或移动类afaik
但你可以在编译器引用的那一行看到一个赋值。您还没有显示rsmap
是什么,但查看std::map
的运算符[]可以发现,它默认构造一个元素,返回对新值的引用,然后您的代码副本分配给它。std::unordered_map
也是如此。
如果你的类不可复制或不可赋值,你就不能这样做——你需要在适当的位置构造对象。emplace
方法实现了这一点,给出了类似于的代码
rsmap.emplace(origUrl, origUrl);
或者,您可以保留现有代码并编写复制/移动构造函数和赋值运算符。
- 为什么std::互斥需要很长的、非常不规则的时间来共享
- 使用 std::condition_variable 触发其他线程.使用哪些互斥锁?
- 将元素添加到 std::list 在多线程中,无需 C++ 互斥锁
- 读取互斥对象范围之外的volatile变量,而不是std::atomic
- 访问共享内存而不使用易失性、std::atomic、信号量、互斥锁和自旋锁
- C++编译错误,std 中的互斥锁不会在 MinGW (GCC 6.3.0) 中命名类型
- 如何使一个类的多个对象具有std::互斥
- std::互斥初始化异常
- 含义std::互斥锁解锁与锁同步以重新获取
- 导致c++ 11 std::互斥锁将被阻塞的线程锁定到被动等待状态
- std::互斥量是否足以实现线程间的数据同步?
- 使用std::互斥对象的数组时,Conditional_variable不会触发
- 无法锁定DLL上的c++ 11 std::互斥锁
- 移动std::互斥锁的构造函数
- 使用MXE gcc构建Qt应用程序时缺少std::互斥锁
- c++ std::互斥锁是如何绑定到资源的?
- 如何安全地删除std::互斥体成员
- 当重写new操作符时,Std::互斥锁挂起
- 对boost::asio管理的线程池使用std::互斥锁
- 用std::互斥对象复制类