Вернуть ссылку на векторную переменную - PullRequest
27 голосов
/ 05 декабря 2011

У меня есть вектор в качестве члена класса, и я хочу вернуть ссылку на него через функцию getVector (), чтобы иметь возможность изменить его позже. Не лучше ли использовать на практике функцию getVector ()? Однако в следующем коде я получил ошибку «квалификаторы отброшены в привязке ссылки типа…». Что должно быть изменено?

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

Ответы [ 4 ]

32 голосов
/ 05 декабря 2011

Поскольку это функция-член 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 во-первых.

14 голосов
/ 05 декабря 2011

Нередко объявляются как константные, так и изменяемые варианты, например:

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
}

и когда это неконстантный метод или клиент содержит неконстантную ссылку, вы можете легально использовать неконстантный метод:

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

так что все работает хорошо (не считая избыточности методов).

2 голосов
/ 05 декабря 2011

Функция getVector может быть объявлена ​​как const. Он возвращает ссылку, которую можно изменить, поэтому, хотя действительная функция ничего не меняет в классе, вызывающая сторона сможет изменять внутренние данные.

Объявите это как:

std::vector<int>& getVector();

Если вы хотите, чтобы функция возвращала вектор, который нельзя изменить, используйте модификатор const как для вектора, так и для функции:

const std::vector<int>& getVector() const;
0 голосов
/ 05 декабря 2011

Причина в том, что функция-член const должна возвращать только ссылки на const.Это связано с тем, что в const-функции каждый элемент данных становится постоянным.

Поэтому вы должны объявить getVector () следующим образом:

std::vector<int> &VectorHolder::getVector() const;
...