Reference to the this pointer: GCC vs clang

This is a follow-up of these questions.

Consider the following code:

struct A {
private:
    A* const& this_ref{this};
};

int main() {
    A a{};
    (void)a;
}

If compiled with the -Wextra , both GCC v6.2 and clang v3.9 show a warning.

Anyway, with the slightly modified version shown below they behave differently:

struct A {
    A* const& this_ref{this};
};

int main() {
    A a{};
    (void)a;
}

In this case GCC doesn't give any warning, clang gives the same warning as returned in the previous example.

The warnings are almost the identical.
It follows the one from clang:

3 : warning: binding reference member 'this_ref' to a temporary value [-Wdangling-field]

Which compiler is right?

I would say that GCC is wrong in this case and I were opening an issue, but maybe it's the opposite because of an arcane corner case of the language.


The reason for this warning is IMO this excerpt from standard (12.2.5):

A temporary bound to a reference member in a constructor's ctor-initializer (12.6.2) persists until the constructor exits.

and since the keyword this is a prvalue expression, during this_ref initialization a temporary will be created and this_ref is bound to that temporary.

But I have doubt whether your reference is actually initialized in ctor-initializer .

If you write:

struct A {
private:
    const int& rr = 1+1;
};

then you will reproduce the exact same problem with gcc, removing private will also remove this warning.

From what I know this pointer might be used in the body of the non-static member function, I have never read that it could be used as argument during default member initialization.


The member declaration

A* const& this_ref{this};

binds a reference to a temporary that only exists during constructor execution (note: this is an rvalue expression).

I'm not sure if this is formally available in that context, but if it is then with any use of that pointer you have serious case of UB.

Re

Which compiler is right?

… a compiler can issue as many diagnostics as it wants. It's not wrong to issue a diagnostic. So per your description, that both accept the code, then either both compilers are right (which I think is most likely), or both are wrong.


this is prvalue, and temporary object will be created when binding reference to a prvalue, so you're binding reference member to a temporary in default member initializer.

And binding reference member to temporary in default member initializer is ill-formed, which is stated by the standard explicitly.

$12.6.2/11 Initializing bases and members [class.base.init]:

A temporary expression bound to a reference member from a default member initializer is ill-formed. [ Example:

struct A {
  A() = default;          // OK
  A(int v) : v(v) { }     // OK
  const int& v = 42;      // OK
};
A a1;                     // error: ill-formed binding of temporary to reference
A a2(1);                  // OK, unfortunately

— end example ]

And see CWG 1696, this is applied to C++14.

链接地址: http://www.djcxy.com/p/93196.html

上一篇: 将R与现有C#网站集成

下一篇: 参考这个指针:GCC vs clang