复制构造函数相关的编译器错误

Posted

技术标签:

【中文标题】复制构造函数相关的编译器错误【英文标题】:Copy constructor related compiler error 【发布时间】:2014-11-14 01:31:04 【问题描述】:

我有一个在两个并发线程之间共享的资源。该资源包含两个线程都需要读取和写入的向量。因此,我通过互斥锁独占访问向量。到目前为止一切顺利,资源共享运行良好,没有任何问题。

但是,当我尝试如下为 sharedResource 编写复制构造函数时,问题就开始了。

class sharedResource
public:
    sharedResource() 
    sharedResource(const sharedResource &other) 
        vec = other.GetVec();
    
    std::vector<int> GetVec() const   
        std::lock_guard<std::mutex> lock(vecMutex); // Gives error
        return vec;
    

private:
    std::vector<int> vec;
    std::mutex vecMutex;
;

int main()

    sharedResource bacon1;
    sharedResource bacon2 = bacon1;
    return 0;

对于这段代码,我得到错误

error C2664: 'std::lock_guard<std::mutex>::lock_guard(const std::lock_guard<std::mutex> &)' : cannot convert argument 1 from 'const std::mutex' to 'std::mutex &'

您能否解释一下为什么会出现错误,以及是否有办法使用互斥锁而不会出现编译器错误。

如果一切都失败了,我将创建一个线程不安全的 GetVec2 成员函数,它将返回 vec 而不经过锁保护。但我想避免这种可能性。

std::vector<int> GetVec2() const 
    return vec;

【问题讨论】:

如果将互斥体声明为mutable 会怎样? @PaulMcKenzie 不知道这是一个选项 请检查您的代码以传递互斥体的副本与传递引用。在处理引用时,请记住方法的任何const-ness。 与您的问题无关,但您可能需要查看Rule of three (or five)。很有可能,您还想在对象被移动或销毁之前锁定此互斥体。 @user3670482 - 您缺少赋值运算符。但是这里有些奇怪——互斥锁是一个非静态成员变量。每个sharedResource 的实例都会有所不同。因此,将互斥锁锁定在一个实例中不会影响另一个实例。换句话说,我在您的设计中看不到互斥锁的实用程序。有人指出我在这里看不到的东西...... 【参考方案1】:

发生这种情况是因为 getVec()const 方法,但 vecMutex 不是 mutable。您应该将 getVec() 设为非 const 以便它可以修改(获取)互斥锁,或者将互斥锁设为 mutable 以便它也可以通过 const 方法获取。我可能会做后者。

【讨论】:

谢谢我在 GCC 中遇到了同样的错误:没有匹配函数调用'std::lock_guard<:mutex>::lock_guard(const std::mutex&)【参考方案2】:

快速的答案是使vecMutex 可变。

mutable std::mutex vecMutex;

您的代码还有另一个非标准问题。您的默认构造函数和复制构造函数声明不正确。应该是这样的:

sharedResource()
sharedResource(const sharedResource &other) 

    vec = other.GetVec();

您还缺少赋值运算符。

【讨论】:

这是否解释了错误文本?我想看看这有什么关系。 也就是说,什么叫lock_guard拷贝构造函数? @ThomasMcLeod - OP 发布的代码有两个错误,一个是他注意到的,另一个显然是他的编译器让他逃脱了。我在回答的第二部分中指出了后者。 我读了几遍才知道@PaulMcKenzie 说的是第二个错误。我一直在看函数的主体,错过了重要的部分。为了其他人的利益,他说如果你在类中内联定义函数,那么你不需要sharedResource::。但是,如果将它们放在类定义之外,则需要将它们称为 sharedResource::sharedResource()sharedResource::sharedResource(const sharedResource &amp;other)

以上是关于复制构造函数相关的编译器错误的主要内容,如果未能解决你的问题,请参考以下文章

虚函数总结

为啥当类包含任何参数化构造函数时编译器不提供默认构造函数? [复制]

为啥这段代码试图调用复制构造函数?

关于复制构造函数的几个问题

填充中编译器生成的复制构造函数之间的不一致

dev_c++ 复制构造函数