这是C ++中“可变”的一个很好的用例吗?

时间:2016-04-28 07:12:23

标签: c++ const mutable

我有以下课程:

class MyClass
{
private:
    mutable int* m_buffer;
public:
    MyClass(void)
      : m_buffer(nullptr)
    {
    }
    void init(void)
    {
        m_buffer = new int[10];
    }
    // This is the only public interface to retrieve m_buffer
    const int* evaluate(int param) const
    {
        for(int i = 0; i < 10; ++i)
            m_buffer[i] = param*10;
        return m_buffer;
    }
};

我已经读过,当它们的状态不影响类外部状态时,应该使用mutable类成员。在上面的代码中,只能通过m_buffer方法检索成员evaluate()。此方法将更改m_buffer的值,但新值仅取决于param参数。在此特定示例中,mutable关键字的使用是否正确?

我可以避免使用mutable

  • 每次调用该函数时都会分配一个新的缓冲区。但是,这会使我的代码变慢,因为缓冲区通常只有几千兆字节。
  • 预先分配输出缓冲区并将其作为参数传递给evaluate函数。但是,这将使我的API更难理解/使用。
  • m_buffer声明为int* const。但是,这不起作用,因为由于设计决定,我无法在构造函数的初始化列表中分配m_buffer

2 个答案:

答案 0 :(得分:3)

对于您展示的代码,您根本不需要使用mutable关键字。

在const成员函数中,this指针是const限定的,那么成员也是const,对于m_buffer它将是int* const(注意它&#39; s不是const int*),这意味着您仍然可以更改m_buffer指向的值,但不能更改自身。

evaluate()中你只是将m_buffer点改为m_buffer,而不是{{1}}本身,所以应该没问题。

答案 1 :(得分:-1)

我的观点是,当用户可以定义这样的场景时,这不是一个好主意:

MyClass evaluator;
const int* arrResult1 = evaluator.evaluate(10);
//use of arrResult1 
const int* arrResult2 = evaluator.evaluate(15);
//use of arrResult1 and arrResult2

在这种情况下,第二次调用evaluate()会破坏arrResult1。

您可以这样更改:

class MyClass
{
private:
    int* m_resultCache;
public:
    MyClass(void)
      : m_resultCache(nullptr)
    {
    }

    ~MyClass() { delete[] m_resultCache; }

    const int* getResult() const { return m_resultCache; }

    void evaluate(int param)
    {
        if (m_resultCache == nullptr)
           m_resultCache = new int[10];

        for(int i = 0; i < 10; ++i)
            m_resultCache[i] = param*10;
    }
};