const cast允许读锁定,这味道不好吗?

时间:2010-01-28 19:55:02

标签: c++ concurrency const

我想对标记为const的对象执行只读方法,但为了安全地执行此操作,我需要锁定读写器互斥锁:

const Value Object::list() const {
  ScopedRead lock(children_);
  ...
}

但是这会打破,因为编译器抱怨“children_”是const等等。我去了ScopedRead类,直到RWMutex类(children_是一个子类)来允许read_lock在const对象上,但我必须写这个:

inline void read_lock() const {
  pthread_rwlock_rdlock(const_cast<pthread_rwlock_t*>(&rwlock_));
}

我一直都知道const_cast是一种代码气味。有什么方法可以避免这种情况吗?

5 个答案:

答案 0 :(得分:13)

使锁可变

mutable pthread_rwlock_t rwlock;

这是使用mutable的常见场景。对象的只读查询(顾名思义)是一种不需要非const访问的操作。当您希望能够修改对象的不可见或具有可观察的副作用的部分时,Mutable被认为是一种很好的做法。您的锁用于确保对对象数据的顺序访问,并且更改它不会影响对象中包含的数据,也不会对以后的调用产生可观察的副作用,因此它仍然遵循对象的常量。

答案 1 :(得分:6)

锁定mutable

答案 2 :(得分:0)

是的,使用可变性。它是为此目的而设计的:其中函数的整个上下文是const(即访问器或其他一些逻辑上只读的操作。)但是互斥锁或引用计数器等需要一些可写访问元素。

该函数应该是const,即使它在内部锁定互斥锁也是如此。这样做会使代码线程中立,而不必公开细节,我认为这是你想要做的。

非常少数需要合法使用const_cast<>的地方,而这不是其中之一。在对象上使用const cast,特别是在const函数中是代码维护的噩梦。考虑:

token = strtok_r( const_cast<char*>( ref_.c_str() ), ":", &saveptr );

事实上,我认为当你在const函数中看到const_cast时,你应该首先使函数成为非const(在你应该摆脱const_cast之后很快再次使函数变为const)< / p>

答案 3 :(得分:0)

好吧,如果我们不允许修改变量的声明,那么const_cast就可以解决了。如果没有,那就让它变得可变就是解决方案。

答案 4 :(得分:-3)

要解决实际问题,请将锁声明为可变。

以下是我的专业意见:

编辑是正确的抱怨,你发现这是轻微的冒犯是正确的。如果执行只读操作需要锁定,并且锁定必须可写入锁定,那么您应该使只读查询需要非const访问。

编辑:好吧,我会咬人。我已经看到这种模式导致你不会想到的地方出现重大的冲击。有没有人知道如果频繁调用tolowertoupper如何成为主要瓶颈,即使使用默认的ASCII语言环境?在为多线程构建的C运行时库的一个特定实现中,有一个锁用于查询该线程的当前语言环境。大约10000次或更多次调用tolower会导致比从磁盘读取文件更多的性能。

仅仅因为你想要只读访问并不意味着你应该隐藏你需要锁定才能获得它的事实。