Почему 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:

  • this указатель;

Во-вторых, временный объект будет создан при привязке ссылки к prvalue,

Временные объекты создаются when a prvalue is materialized so that it can be used as a glvalue, which occurs (since C++17) в следующих ситуациях:

Вот почему GCC дает предупреждение, потому что this_ref привязан к временному созданному. (И затем побейте позже, что приведет к UB.)