Почему я получаю следующую ошибку: «возвращаем ссылку на временный [-Werror = return-local-addr]» - PullRequest
0 голосов
/ 26 июня 2018

с учетом следующего кода:

#include <set>

using std::set;

class Pool {
    set<int> s;
public:   
    typedef typename set<int>::iterator Iterator;
    const Iterator& begin() const {
      return s.begin(); //** error
    }
};    

Почему я получаю следующую ошибку (я понимаю значение ошибки, но я не понимаю, почему я получаю ее в этом случае)?

возврат ссылки на временный [-Werror = return-local-addr]

Как я могу это исправить?

Ответы [ 2 ]

0 голосов
/ 26 июня 2018
const Iterator& begin() const {
  return s.begin(); //** error
}

недопустимо, поскольку результат s.begin() является временным объектом, и поэтому вы не можете вернуть ссылку на него. Может быть, если вы посмотрите на этот эквивалентный код, он будет понятнее?

const Iterator& begin() const {
  Iterator it = s.begin();
  return it; //** error
}

Возвращение константной ссылки на итератор в любом случае не имеет особого смысла, так как вы не сможете переместить местоположение, на которое указывает итератор. Вы должны всегда возвращать итераторы по значению, таким образом, вызывающая сторона может свободно делать копии итератора и изменять их местоположение. Например, если бы вы могли заставить свой код скомпилировать следующий код вызова, это не сработало бы:

Pool p;
const Pool::Iterator& it = p.begin();
++it; //error it is constant

Пользователь может исправить свой код, скопировав возвращенную ссылку в новый объект:

Pool p;
Pool::Iterator it = p.begin();
++it; //no error

Поскольку ваши пользователи не смогут использовать ссылку, вы не можете вернуть ее лучше, просто чтобы вернуться по значению:

const Iterator begin() const {
  return s.begin();
}

Обратите внимание, что std::set не похож на большинство других контейнеров и не позволяет изменять значения через его итераторы: https://en.cppreference.com/w/cpp/container/set/begin

Поскольку итератор и const_iterator являются постоянными итераторами (и на самом деле могут быть одного типа), невозможно изменить элементы контейнера с помощью итератора, возвращаемого любой из этих функций-членов.

0 голосов
/ 26 июня 2018

Функция set<...>::begin возвращает свой итератор по значению . Поскольку вы нигде не храните это значение, это временное значение, и вы не можете иметь ссылки на временные значения.

Простое решение для вашей функции: также возврат по (неконстантному) значению.

...