我有以下错误:
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;
^~~~~~~~
...已经提出了一些问题(例如this one和that one)。基于这些,我尝试了以下类代码:
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
)。
所以我不是在复制或移动课程,但是那会出问题呢?我怎样才能改变我的代码以使其有效?
编辑:
完整错误:
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
中给出错误。
答案 0 :(得分:2)
你的错误意味着某个分配操作试图在某个地方发生......
在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
成员函数的成员;这里通常是为了能够从const
成员函数锁定/解锁互斥锁。
答案 1 :(得分:0)
错误的第一位是什么意思?
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
成员不可复制
但是,您真正的问题是编译器首先尝试使用它的原因:
所以我不是在复制或移动课程
但你可以在编译引用的行上看到一个赋值。你没有显示rsmap
是什么,但查看std::map
的operator []表明它默认构造一个元素,返回对新值的引用,然后你的代码复制 - 赋值给它。 std::unordered_map
也是如此。
如果您的类不可复制或可分配,则无法执行此操作 - 您需要构建对象。 emplace
方法执行此操作,代码如下:
rsmap.emplace(origUrl, origUrl);
或者,您可以保留现有代码并编写复制/移动构造函数和赋值运算符。