【问题标题】:C++ passing a mutex to a member variable in the constructorC ++将互斥锁传递给构造函数中的成员变量
【发布时间】:2017-10-20 13:21:22
【问题描述】:

我在将互斥锁传递给我的班级时遇到问题。我有一个名为Test 的类,其中有一个名为m_Mutex 的成员变量。在构造函数中我想把参数mutex传给m_Mutex。

我的班级:

#include <mutex>

class Test
{
public:
    Test(mutex &mtx) :
        m_Mutex(mtx)
    {
    }

private:
    mutex m_Mutex;
};

我的主要:

int main()
{
   mutex mutex1;
   Test t(mutex1);
   return 0;
} 

错误:

函数“std::mutex::mutex(const std::mutex &)”(在第 88 行声明 “c:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.11.25503\include\mutex") 不能被引用——它是一个被删除的函数

为什么我会收到此错误,我该如何解决我能够通过互斥锁的问题?

【问题讨论】:

  • 听起来像是 XY 问题,为什么首先需要传递互斥锁?

标签: c++ class mutex member


【解决方案1】:

简而言之:你不能。互斥锁既不可复制也不可移动。他们没有充分的理由。但是,如果您想实现这一点,您可以使用 unique_ptr 传递它:

class A {
   unique_ptr<mutex> mutexPtr;

   A(unique_ptr<mutex> ptr) : mutexPtr(std::move(ptr)) { }
};

A a{std::make_unique<mutex>()};

注意,如果你想在不同对象之间共享互斥体,你应该使用 shared_ptr 或weak_ptr 来代替。

【讨论】:

  • 不知道为什么 OP 需要通过它,这个答案可能不适用。
  • 一般来说,拥有可移动/可复制的互斥体并不是一个好主意。我认为 OP 有充分的理由并且知道他在做什么。这就是为什么我写互斥锁的构造是有充分理由的。
  • 很好的理由是 OP 需要共享该互斥体,否则最好将它放在类中。如果是这样,你的答案是错误的。
  • 确实如此,但修改很少:然后使用 shared_ptr 。我会相应地调整答案。
  • 但是你的答案应该使用shared_ptr 我看不出有任何理由在这里使用unique_ptr。
【解决方案2】:

在构造函数中我想把参数mutex传给m_Mutex

很遗憾,你不能。 std::mutex 不可复制且不可移动。如果您想在其他地方声明互斥锁,您可以做的一件事是存储对互斥锁的引用,例如

class Test
{
public:
    Test(mutex &mtx) :
        m_Mutex(mtx)
    {
    }

private:
    mutex& m_Mutex;
};

【讨论】:

  • 这是潜在的危险,因为在 Test 内部无法确定对互斥锁的引用是否仍然有效。如果您想共享所有权,则应使用 shared_ptr(或weak_ptr)。
  • 我可以在 Test 类的其他函数中使用此代码锁定和解锁互斥锁吗? m_Mutex.lock() 和 m_Mutex.unlock()?
  • @User987123 是的,但是它自己的类变得不可复制且不可移动。使用智能指针的 Jodocus 解决方案将允许您移动/可能复制它。
【解决方案3】:
#include <mutex>

class Test
{
public:
Test(std::mutex &mtx) :         
    m_Mutex(mtx)
{
}

private:
std::mutex &m_Mutex;           // note the "&"
};


int main()
{
 std::mutex mutex1;
 Test t(mutex1);
 return 0;
}

【讨论】:

  • 这应该真正解释了为什么成员变量需要作为参考才能成为一个好的答案(参见 NathanOlivers 的答案作为示例)。
【解决方案4】:

只需将互斥锁保留在您的类中(可能作为静态成员),如果您需要允许其他类使用它,请提供访问权限:

class Test 
{
public:
    Test() {}
    std::mutex &mux() { return m_Mutex; }
private:
    mutex m_Mutex;
};

甚至这个:

class Test {
public:
    using lock_t = std::scoped_lock<std::mutex>;
    Test() {}

    lock_t lock() { return lock_t( m_Mutex ); }
private:
    mutex m_Mutex;
};

用法:

Test t;
{
    auto lock = t.lock();
    // object t is locked till end of the block
}

【讨论】:

    【解决方案5】:

    只是作为参考

    对于您的类的所有实例,您的互斥锁必须相同,如果不是这种情况,您在类的一个实例中执行的锁定不会对另一个实例有效。

    #include <mutex>
    #include <iostream>
    
    using namespace std;
    
    class Test
    {
    public:
        Test(mutex &mtx) :
            m_Mutex(mtx)
        {
                m_Mutex.lock();
                i++;
                cout << "Test " <<i<<endl;
                m_Mutex.unlock();
        }
    
    private:
        mutex& m_Mutex;
        static int i;
    };
    
    int Test::i =0;
    
    int main()
    {
       mutex mutex1;
       Test t1(mutex1);
       Test t2(mutex1);
       return 0;
    } 
    

    现场观看:https://wandbox.org/permlink/6YJFG3MI7m7RbfoL

    【讨论】:

    • 为什么需要一个 const 互斥锁?你打算如何锁定它?
    • std::mutex::lock() 不是 const 方法。
    • 对不起,我想指出,将其设为 const 是合乎逻辑的,但它不起作用,但我发现它会推广错误的代码,这是不好的。
    猜你喜欢
    • 2021-05-15
    • 1970-01-01
    • 1970-01-01
    • 2012-01-12
    • 1970-01-01
    • 2020-11-19
    • 2012-10-06
    • 1970-01-01
    • 2021-02-05
    相关资源
    最近更新 更多