c++ - 这对于 const 来说太不可改变了吗?

标签 c++ constants mutable

基本上,我有以下情况。注意: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_;
};

因此尝试确保 const 的正确性,intermediate_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_;
};

想法?

最佳答案

我认为这是对 mutable 的不当使用。以我的经验,mutable 用于辅助私有(private)成员变量,它们本质上不能声明为 const,但不要修改公共(public)接口(interface)的“概念常量”。

以 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_;
};

这里的要点是声明的数据可变(在本例中是守卫)确实改变了(它被锁定和解锁)但这对常量性没有影响用户的观点。 最终,尽管有可变 Mutex,您仍然无法更改 const data_ 成员变量并且编译器会强制执行此操作

在您的情况下,您确实希望 intermediate_buffer 为 const,但您通过声明它是可变的来明确告诉编译器它不是。结果是您可以更改数据而编译器对此无能为力

看出区别了吗?

如果您真的希望接口(interface)符合 const 协议(protocol),请通过如下方式使其明确:

    class A { 
    public:    

        A( void* input_data );// I assume this deep copies.

        void foo() const;

        void bar();

        private:    
            const void* intermediate_buffer_;   
            void* something_; 
    };

现在责任真正在用户身上,由编译器强制执行,不管注释说什么,也不使用任何可变的。如果他们知道 input_data 已经改变,他们将不得不创建一个新的,最好是 const。

关于c++ - 这对于 const 来说太不可改变了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22666517/

相关文章:

c++ - 假设派生类的指针与第一个基类的指针相同有多安全?

c++ - 使用 boost vector 和字符串的奇怪 boost program_options 问题

functional-programming - 有状态编程的优点?

c++ - 使用 std::result_of 的意外 SFINAE 失败

c++ - 软件产品应该如何处理访问冲突

C++ 常量 : how come the compiler doesn't give a warning/error

ruby-on-rails - Rails中的常量哈希的国际化3

java - 如果常量接口(interface)反模式是一种犯罪行为,那么 Swing 为什么要这样做呢?

rust - 特征对象的 &mut 和 ref mut 之间的区别

java - 以下类中的对象是不可变的吗?