Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 应该互斥';s锁定/解锁功能应为“;常数;?_C++_Multithreading_Api - Fatal编程技术网

C++ 应该互斥';s锁定/解锁功能应为“;常数;?

C++ 应该互斥';s锁定/解锁功能应为“;常数;?,c++,multithreading,api,C++,Multithreading,Api,我正在维护一个包含互斥类的库。我无法决定这个类公开的lock()和unlock()函数是否应该是const。我在Web上寻找类似的代码,并且可以找到这两种实现 第一个实现,lock()和unlock()不是常量。这意味着在const函数中使用Mutex类的人应该付出额外的努力来调用Mutex的函数: class Mutex { public: void lock(); void unlock(); }; class Foo { public: void getBar(Bar&

我正在维护一个包含互斥类的库。我无法决定这个类公开的lock()和unlock()函数是否应该是const。我在Web上寻找类似的代码,并且可以找到这两种实现

第一个实现,lock()和unlock()不是常量。这意味着在const函数中使用Mutex类的人应该付出额外的努力来调用Mutex的函数:

class Mutex
{
public:
   void lock();
   void unlock();
};

class Foo
{
public:
   void getBar(Bar& bar) const
   {
      m_mutex.lock();
      bar = m_bar;
      m_mutex.unlock();
   }

private:
   // Mutable, responsability of the user (or we could use a const_cast when needed)
   mutable Mutex m_mutex;
   Bar   m_bar;
};
class Mutex
{
public:
   void lock() const;
   void unlock() const;
};

class Foo
{
public:
   void getBar(Bar& bar) const
   {
      m_mutex.lock();
      bar = m_bar;
      m_mutex.unlock();
   }

private:
   Mutex m_mutex;
   Bar   m_bar;
};
第二个实现,lock()和unlock()是常量,即使听起来不太自然(我们修改互斥实例),但用户在其常量函数中调用这些函数时不必费心:

class Mutex
{
public:
   void lock();
   void unlock();
};

class Foo
{
public:
   void getBar(Bar& bar) const
   {
      m_mutex.lock();
      bar = m_bar;
      m_mutex.unlock();
   }

private:
   // Mutable, responsability of the user (or we could use a const_cast when needed)
   mutable Mutex m_mutex;
   Bar   m_bar;
};
class Mutex
{
public:
   void lock() const;
   void unlock() const;
};

class Foo
{
public:
   void getBar(Bar& bar) const
   {
      m_mutex.lock();
      bar = m_bar;
      m_mutex.unlock();
   }

private:
   Mutex m_mutex;
   Bar   m_bar;
};

你喜欢什么样的解决方案?我希望你的意见能帮助我做出决定。

如果你想从互斥类派生类,那么将两个函数设为常量(有些)是有意义的,然后你可以在派生类自己的常量函数中调用它

像这样:

class Foo : public Mutex {
public:
    void
        bar() const { lock(); doSomething(); unlock(); }
}

我更喜欢第一个选项,即在客户机代码中设置互斥对象。这样,类的用户明确地知道他正在从他的const函数调用一个非const函数。事实上,如果您看到类的MFC实现,您可以看到
Lock
Unlock
方法是非常量的。

mutable
就是为这类东西设计的。也就是说,
mutable
适用于不参与对象逻辑常量的事物。(如果一个值为“逻辑常量”,则表示“主要”值为常量;对象的值从外部看无法更改。)

对象的值独立于互斥体的状态(它只是提供一致性的一个实现细节,并且它的状态在类之外是未知的),这是互斥体应该是可变的一个好迹象


注意,您不应该走
const\u cast
路线。如果您这样做了:

const Foo f;

Bar b;
f.getBar(b); // takes const off of mutex, modifies (bang you're dead)

首选第一种实现:const条件指的是逻辑const二进制const:互斥是一个助手类-它实际上不会更改客户端代码的逻辑状态,但更改它会更改客户端代码的二进制状态

因此,互斥锁应该在客户机代码中设置为
可变的


如果在代码中缓存一些代价高昂的操作结果,也会出现同样的情况:您将chache变量声明为可变的,因此在计算它时,您不需要丢弃类的
常量。

这对我来说也更自然。另一个例子是Qt QMutex实现,其锁定和解锁也不是常量:这是否意味着如果一个类具有可变成员,编译器/链接器将以不同的方式处理它(即,与“普通”常量类不同,其实例不能放入常量地址空间)@Péter:Yup。§3.9.3/3:“const限定类对象的每个非静态、非可变、非引用数据成员都是const限定的…”因此
mutable
成员没有获得const限定。我认为这是一个坏例子。使用继承向类中添加一些可以通过组合轻松添加的内容是不好的风格。@Martin:这并不比在封装中使用
mutable
作弊更糟糕:两种方法都有优点和缺点。在这种情况下,这完全取决于互斥类的使用模式,以及它对程序员的感觉如何,依我看。当我有一个函数,它接受一个参数,该参数将以getBar中的方式进行修改时,我喜欢将其称为fillBar,这样它的功能就不会含糊不清。