如何使用std :: mutex获得类的多个对象?

时间:2016-05-18 17:51:04

标签: c++ 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;
            ^~~~~~~~

...已经提出了一些问题(例如this onethat 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中给出错误。

2 个答案:

答案 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);

或者,您可以保留现有代码并编写复制/移动构造函数和赋值运算符。