Почему GCC 5.3.0 дает предупреждение при привязке ссылки к указателю "this"
Вот минимальный пример:
class A
{
A* const& this_ref;
public:
A() : this_ref(this) {}
};
GCC 5.3.0 дает предупреждение:
предупреждение: временная привязка к "A:: this_ref" сохраняется только до тех пор, пока конструктор выходит [-Wextra] A(): this_ref (this) {}
Является ли this
временным? Что... MSVC 2015 молчит об этом, и ссылаясь на членов класса на this_ref->member
вне конструктора, в моем случае дает ожидаемое поведение (но может быть просто случай UB, не уверен).
EDIT:
Обратите внимание, что этот вопрос расширяет один связанный как возможный дубликат, потому что это не общий вопрос о способе создания такой ссылки, а о предупреждении GCC (и возможных других компиляторов, отличных от MSVC) при создании.
Ответы
Ответ 1
Вы создаете оборванную ссылку. Ваш код ничем не отличается от этого кода:
struct X
{
const int & r;
X() : r(5) {}
}; // ^^^^ dangles
Нет объекта, называемого this
. this
- это ключевое слово, а при использовании в качестве выражения это prvalue (временное), содержащее адрес текущего экземпляра.
Вот еще один пример создания аналогично болтающейся ссылки из того, что выглядит как объект, но не:
struct Y
{
int a[10];
int* const & r;
Y() : r(a) {}
};
Здесь a
- именованный объект (lvalue), но в инициализаторе r
выражение a
является prvalue (а именно, результатом распада массива).
Общее сообщение состоит в том, что вы должны быть осторожны с языковой функцией, которая позволяет ссылаться на константные ссылки на значения r. Его основная цель - облегчить вызов функций, но другие его применения намного более увлекательны.
Ответ 2
Является ли this
временным?
Чтобы быть точным, this
не является временным, но здесь создается временное.
Во-первых, this
prvalue,
Следующие выражения представляют собой выражения prvalue:
Во-вторых, временный объект будет создан при привязке ссылки к prvalue,
Временные объекты создаются when a prvalue is materialized so that it can be used as a glvalue, which occurs (since C++17)
в следующих ситуациях:
Вот почему GCC дает предупреждение, потому что this_ref
привязан к временному созданному. (И затем побейте позже, что приведет к UB.)