У меня есть код, который имеет дело с RVALED контейнерами STL.
Мой вопрос: почему функции-члены, которые возвращают элемент из rvalued-stl-container, как в:
vector<int>{1}.front()
возвращает lvalue, а не rvalue? Стандарт определяет, что членом объекта rvalue является rvalue. Я знаю, что могу явно переместить возвращаемый элемент с std::move
, Но какова логика наличия возвращаемого типа lvalue, когда возвращаемое значение явно является rvalue?
Если вы используете такое выражение в качестве аргумента некоторой перегруженной функцией valuness функции, будет выбрана неправильная перегрузка, и вызываемая функция получит ссылку на lvalue (которая вскоре станет висячей).
Может быть добавление outplace_front()
а также outplace_back()
для исходящих значений будет лучше имена в духе emplace_front()
а также emplace_back()
для входящих значений.
Как только компилятор решил вызвать конкретную функцию-член (int &std::vector<int>::front()
скажем, система типов знает только, что int &
возвращается, поэтому он должен рассматривать это как lvalue, даже если его срок жизни ограничен временным сроком действия владельца.
До C ++ 11 не было возможности перегружать функцию-член в соответствии с категорией значений объекта, к которому она вызывается (см. Что такое "Rvalue ссылка для * этого"?), только по cv-квалификации объекта; и неконстантный временный явно не const
так чтоconst
перегрузки должны быть доступны.
Наряду с потенциально висящими ссылками lvalue, которые вы определили, это привело в C ++ 03 к ситуации, когда operator<<
на временной ostream
может быть вызван с char
(оператор функции-члена), но не с string
(свободный оператор); C ++ 11 исправляет это с помощью свободных перегрузок операторов для ссылок на rvalue и rvalue *this
перегрузка для функций-членов.
Rvalue *this
допускает три перегрузки для front
:
T &front() & { return data_[0]; }
const T &front() const & { return data_[0]; }
T &&front() && { return std::move(data_[0]); }
Тело другой функции для перегрузки rvalue является чем-то вроде бородавки; это потому, что ref-квалификатор не влияет на член *this
доступ в теле функции-члена.