Const вектор подразумевает const-элементы?
Значит ли const vector<A>
, что его элементы также const
?
В приведенном ниже коде
v[0].set (1234);
в void g ( const vector<A> & v )
создает ошибку компилятора
const.cpp: 28: 3: ошибка: функция-член 'set' не жизнеспособна: 'this'аргумент type 'const value_type' (aka 'const A'), но функция не отмечена как const
Почему?
Но (*v[0]).set(1234);
в void h ( const vector<A *> & v )
ОК для компилятора.
Какая разница между версиями?
// ...........................................................
class A {
private:
int a;
public:
A (int a_) : a (a_) { }
int get () const { return a; }
void set (int a_) { a = a_; }
};
// ...........................................................
void g ( const vector<A> & v ) {
cout << v[0].get();
v[0].set (1234);
} // ()
// ...........................................................
void h ( const vector<A *> & v ) {
cout << (*v[0]).get();
(*v[0]).set(1234);
} // ()
Ответы
Ответ 1
Первая версия
v[0].set (1234);
не компилируется, потому что он пытается изменить первый элемент вектора, возвращенный ему ссылкой. Компилятор считает это изменением, потому что set(int)
не помечен const
.
Вторая версия, с другой стороны, только читает из вектора
(*v[0]).set(1234);
и вызывает set
в результате разыменования константы ссылки на указатель, который он возвращает.
Когда вы вызываете v[0]
в векторе const
, вы возвращаете ссылку const
на A
. Когда тип элемента является указателем, вызов set
на нем в порядке. Вы можете изменить второй пример на
v[0]->set(1234);
и получите тот же результат, что и раньше. Это связано с тем, что вы получаете ссылку на указатель, который является константой, но элемент, на который указывает этот указатель, не является константой.
Ответ 2
Да, const vector
предоставляет доступ к элементу, как если бы они были const
(то есть давали ссылки const
). В вашей второй функции не объекты типа A
являются const
, а указывают на них. Указатель const
не означает, что объект, на который указывает указатель, равен const
. Чтобы объявить указатель на константу, используйте тип A const *
.
Ответ 3
Таким образом, объект const может вызывать только вызовы методов const. То есть:
class V {
public:
void foo() { ... } // Can't be called
void bar() const { ... } // Can be called
};
Итак, посмотрим на оператор vector []:
reference operator[]( size_type pos );
const_reference operator[]( size_type pos ) const;
Итак, когда векторный объект const, он вернет a const_reference
.
О программе: (*v[0]).set(1234);
Давайте сломаем это:
A * const & ptr = v[0];
A & val = *ptr;
val.set(1234);
Обратите внимание, что у вас есть постоянный указатель на переменные данные. Таким образом, вы не можете изменить то, на что указали, но вы можете изменить значение, на которое указывает указатель.