Изменяемый спецификатор C ++

Когда я могу, и когда я не могу назвать переменную изменяемой?

Это очень ясно со значением int / float / bool.
А как насчет массива? Можно ли назвать родной массив mutable, если я собираюсь добавить элементы к нему? То же самое с std::vector,

Еще один пример. У меня есть объект A, который сохраняет ссылку (B &б) к другому объекту B. Объект B имеет собственный массив, который я буду перераспределять / std :: vector (который, я думаю, аналогичен в данном конкретном случае). Псевдо-код:

struct B{
std::vector<int> arr;
// int *arr;              //Or this
void changeArr(){
arr.push_back(90);
}
}

struct A{
A(B &b) : b(b){};
mutable B &b;     // is it ok to have it "mutable"?
//mutable B b;    // or even this?
void fire() const{
b.arr.push_back(125);
// Or
b.changeArr();
}
}

Могу я позвонить B &b изменяемые?


ОБНОВИТЬ

В соответствии с http://en.cppreference.com/w/cpp/language/cv:

mutable — определяет, что член класса не влияет на
внешне видимое состояние класса.

Что это externally visible state of the class ? Я изменяю это, когда я увеличиваю размер массива, перераспределяю что-то? Если нет, то когда это вообще изменится?

1

Решение

Давайте приведем два классических примера того, где мутабельность полезна:

class prime_caclulator {
private:
mutable std::vector<int> m_primes;

public:
get(int n) const {
// 1. If the nth prime is in m_primes, return it.
// 2. Otherwise, calculate the nth prime.
// 3. Store the nth prime in m_primes.
// 4. Return that prime.
}
};

Здесь у нас есть константная функция get() это не должно изменить внутреннее состояние этого объекта, чтобы вычислить n-е простое число. Но может быть полезно отслеживать ранее вычисленные простые числа, чтобы улучшить производительность этого объекта.

Это внутреннее состояние, которое здесь мы называем m_primesможет измениться, когда get() называется, поэтому мы должны пометить его как изменяемый. Обратите внимание, что изменяющееся содержимое этого объекта только изменяет время, которое занимает этот вызов, а не то, что он возвращает в итоге.

template <typename T>
class thread_safe_queue {
private:
mutable std::mutex m_mutex;
std::queue<T> m_queue;

public:
size_t size() const {
std::lock_guard<std::mutex> lock(m_mutex);
return m_queue.size();
}

void push(T value) {
std::lock_guard<std::mutex> lock(m_mutex);
m_queue.push(value);
}

T pop() {
std::lock_guard<std::mutex> lock(m_mutex);
T top = m_queue.front();
m_queue.pop();
return top;
}
};

В этом случае, если бы у нас не было изменяемого мьютекса, мы бы не смогли size() быть const, потому что мы модифицируем m_mutex в процессе этой функции.

3

Другие решения


По вопросам рекламы [email protected]