Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why GCC 5.3.0 gives warning when binding reference to "this" pointer

Here is the minimal example:

class A
{
    A* const& this_ref;
public:
    A() : this_ref(this) {}
};

GCC 5.3.0 gives warning:

warning: a temporary bound to 'A::this_ref' only persists until the constructor exits [-Wextra] A() : this_ref(this) {}

Is this a temporary then? What the... MSVC 2015 is silent about this, and referring to class members by this_ref->member outside the constructor in my case gives expected behaviour (but might be just a case of UB, not sure).


EDIT:

Note this question extends one linked as possible duplicate, because it's not generic question about way to create such reference, but about warning GCC (and possible other compilers other than MSVC) produces when creating one.

like image 753
xinaiz Avatar asked Sep 12 '16 09:09

xinaiz


2 Answers

You are creating a dangling reference. Your code is no different from this code:

struct X
{
    const int & r;
    X() : r(5) {}
};     // ^^^^ dangles

There is no "object" called this. this is a keyword, and when used as an expression, it is a prvalue (a temporary) containing the address of the current instance.

Here's another example of the creation of a similarly dangling reference from something that looks like an object but isn't:

struct Y
{
    int a[10];
    int* const & r;

    Y() : r(a) {}
};

Here, a is a named entity (an lvalue), but in the initializer of r, the expression a is a prvalue (namely the result of the decay of the array).

The overall message is that you should be careful with the language feature that allows const lvalue references to bind to rvalues. Its main purpose is to make function calls easy, but its other uses are much hairier.

like image 100
Kerrek SB Avatar answered Oct 15 '22 06:10

Kerrek SB


Is this a temporary then?

To be precise, this is not temporary, but a temporary is created here.

Firstly, this is prvalue,

The following expressions are prvalue expressions:

  • the this pointer;

Secondly, temporary object will be created when binding reference to a prvalue,

Temporary objects are created when a prvalue is materialized so that it can be used as a glvalue, which occurs (since C++17) in the following situations:

  • binding a reference to a prvalue

That's why GCC gives warning, because this_ref is bound to a temporary created. (And then become dangled later, which leads to UB.)

like image 5
songyuanyao Avatar answered Oct 15 '22 06:10

songyuanyao