2016-04-28 2 views
2

У меня есть следующий класс:Является ли это хорошим вариантом использования «mutable» в C++?

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 в списке инициализаторов конструктора.
+0

Кто отвечает за вызов '' delete' на m_buffer'? Или, другими словами, кто * владеет * 'm_buffer'? –

+2

Тот, кто сделал это «конструкторское решение» о инициализации в функции члена 'init', думает, что он/она работает с C. – Shoe

+0

Я думаю, что концептуально' оценка' * * влияет на внешнее состояние класса. '' '' '' '' эффективно выставляет внутренний 'm_buffer' извне. –

ответ

3

Для кода, который вы указали, вам не нужно использовать ключевое слово mutable.

В константной функции члена, то this указателя сопзИте квалификацию, то члены будут Const тоже, m_buffer будет int* const (обратите внимание, что это не const int*), это означает, что вы все еще может изменить значение указываемого m_buffer , но не сам.

И в evaluate() вы меняете только валун m_buffer, а не m_buffer, так что все должно быть хорошо.

+0

Вы абсолютно правы! Я не знаю, о чем я думал! Извиняюсь за глупый вопрос и большое спасибо! – AstrOne

+0

@AstrOne Glad может помочь. Пожалуйста. :) – songyuanyao

-1

Мое мнение, что это не очень хорошая идея, когда пользователь может определить такой сценарий:

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

В этом случае arrResult1 будет испорчена по телефону evaluate() во второй раз.

Вы можете изменить его следующим образом:

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; 
    } 
}; 
+0

На самом деле это не вопрос. OP хочет «оценивать» как 'const'. – Henrik

+0

@ Хенрик, ты прав! Я просто хотел указать, что такой дизайн может вызвать проблемы. –

Смежные вопросы