基本上,我有以下情况.注意:void*用于表示任意数据,它在实际应用程序中强类型.
class A
{
public:
//uses intermediate buffer but doesn't change outward behavior
//intermediate buffer is expensive to fill
void foo(void* input_data);
//uses intermediate buffer and DOES explicitly change something internally
//intermediate buffer is expensive to fill
void bar(void* input_data);
//if input_data hasn't changed since foo, we can totally reuse what happened in foo
//I cannot check if the data is equal quickly, so I allow the user to pass in the
//assertion (put the honerous on them, explicitly tell them in the comments
//that this is dangerous to do, ect)
void bar(void* input_data, bool reuse_intermediate);
private:
void* intermediate_buffer_;
void* something_;
};
Run Code Online (Sandbox Code Playgroud)
因此,尝试const正确性时,middle_buffer_永远不会暴露,因此它适合使用mutable变量的定义.如果我从不重用这个缓冲区,或者我在使用缓存值之前检查了相等的input_data,那将是故事的结束,但是由于reuse_intermediate我觉得我有一半暴露它,所以我不确定是否或不是以下有意义.
class A
{
public:
//uses intermediate buffer but doesn't change something
//intermediate buffer is expensive to fill
void foo(void* input_data) const;
//uses intermediate buffer and DOES explicitly change something internally
//intermediate buffer is expensive to fill
void bar(void* input_data);
//if input_data hasn't changed since foo, we can totally reuse what happened in foo
//I cannot check if the data is equal quickly, so I allow the user to pass in the
//assertion (put the honerous on them, explicitly tell them in the comments
//that this is dangerous to do, ect)
void bar(void* input_data, bool reuse_intermediate);
//an example of where this would save a bunch of computation, though
//cases outside the class can also happen
void foobar(void* input_data)
{
foo(input_data);
bar(input_data,true);
}
private:
mutable void* intermediate_buffer_;
void* something_;
};
Run Code Online (Sandbox Code Playgroud)
思考?
我认为这是不当使用的mutable.根据我的经验mutable,用于辅助私有成员变量,它们本质上不能声明为const,但不要修改公共接口的"概念常量".
以Mutex成员变量和'线程安全getter'为例:
class Getter {
public:
Getter( int d, Mutex & m ) : guard_( m ), data_( d ) { };
int get( ) const { Lock l(guard_); return data_; };
private:
mutable Mutex guard_;
const int data_;
};
Run Code Online (Sandbox Code Playgroud)
这里的要点是声明的数据mutable(在本例中为guard)确实发生了变化(它被锁定和解锁),但从用户的角度来看这对constness没有影响. 最终,尽管有可变的互斥锁,但仍然无法更改const data_成员变量,编译器会强制执行此操作.
在你的情况下,你真的希望intermediate_buffer是const,但你明确告诉编译器它不是通过声明它是可变的.结果是您可以更改数据,编译器无法对其进行任何操作.
看到不同?
如果您真的希望接口符合const协议,请通过以下方式明确说明:
class A {
public:
A( void* input_data );// I assume this deep copies.
void foo() const;
void bar();
private:
const void* intermediate_buffer_;
void* something_;
};
Run Code Online (Sandbox Code Playgroud)
现在,责任真正在用户身上,并由编译器强制执行,无论注释说什么,也不使用任何可变的.如果他们知道input_data已经改变,他们将不得不创建一个新的,最好是const.