Возвратить ссылку на переменную-член вектора
У меня есть вектор как член в классе, и я хочу вернуть ссылку на него через функцию getVector(), чтобы иметь возможность модифицировать ее позже. Разве лучше не использовать функцию getVector() как const? Тем не менее, я получил ошибку "квалификаторы, сброшенные в ссылке привязки типа..." в следующем коде. Что нужно изменить?
class VectorHolder
{
public:
VectorHolder(const std::vector<int>&);
std::vector<int>& getVector() const;
private:
std::vector<int> myVector;
};
std::vector<int> &VectorHolder::getVector() const
{
return myVector;
}
Ответы
Ответ 1
Так как это функция-член const
, тип возврата не может быть неконстантной ссылкой. Сделайте его const
:
const std::vector<int> &VectorHolder::getVector() const
{
return myVector;
}
Теперь все в порядке.
Почему все нормально? Поскольку в функции-члене const
каждый член становится const таким образом, что его нельзя изменить, что означает, что myVector
является вектором const
в функции, поэтому вам нужно сделать тип возврата const
, если он возвращает ссылку.
Теперь вы не можете изменить один и тот же объект. Посмотрите, что вы можете сделать, а что нет:
std::vector<int> & a = x.getVector(); //error - at compile time!
const std::vector<int> & a = x.getVector(); //ok
a.push_back(10); //error - at compile time!
std::vector<int> a = x.getVector(); //ok
a.push_back(10); //ok
Кстати, мне интересно, зачем вам это нужно VectorHolder
.
Ответ 2
это не редкость объявлять как const, так и изменчивые варианты, например:
std::vector<int>& VectorHolder::getVector() {
return myVector;
}
const std::vector<int>& VectorHolder::getVector() const {
return myVector;
}
Основная проблема с вашей программой заключается в том, что вы возвращаете неконстантную ссылку из метода const.
std::vector<int>& VectorHolder::getVector() const {
return myVector; // << error: return mutable reference from const method
}
поэтому вы создаете константу, используя эту форму:
const std::vector<int>& VectorHolder::getVector() const {
return myVector; // << ok
}
и когда это находится в методе non const или клиент содержит неконстантную ссылку, то вы можете юридически использовать метод non-const:
std::vector<int>& VectorHolder::getVector() {
return myVector; // << ok
}
наконец, вы можете вернуть значение (в некоторых случаях):
std::vector<int> VectorHolder::getVector() const {
return myVector; // << ok
}
потому что копия не требует мутации и не подвергает воздействию внутренних данных.
чтобы вы в конечном итоге объявляли оба варианта довольно часто.
результаты объявления обоих:
VectorHolder m;
const VectorHolder c;
m.getVector().size(); // << ok
c.getVector().size(); // << ok - no mutation
m.getVector().push_back(a); // << ok
c.getVector().push_back(a); // << error: attempt to mutate const reference because the const vector is returned
так что все это хорошо работает (кроме избыточности методов).
Ответ 3
Функция getVector
может быть объявлена как const
. Он возвращает ссылку, которая может быть изменена, поэтому, пока фактическая функция ничего не изменяет в классе, вызывающий может изменять внутренние данные.
Объявите его как:
std::vector<int>& getVector();
Если вы хотите, чтобы функция возвращала вектор, который не может быть изменен, используйте модификатор const
как для вектора, так и для функции:
const std::vector<int>& getVector() const;
Ответ 4
Причина в том, что функция-член const должна возвращать только ссылки const. Это связано с тем, что в функции const каждый член данных становится постоянным.
Поэтому вы должны объявить getVector() следующим образом:
std::vector<int> &VectorHolder::getVector() const;