6

这是这些 问题的后续。

考虑以下代码:

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

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

如果使用 编译-WextraGCC v6.2 和clang v3.9 都会显示警告。

无论如何,使用下面显示的稍微修改的版本,它们的行为会有所不同:

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

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

在这种情况下, GCC不给出任何警告,clang给出与前面示例中返回的相同的警告。

警告几乎相同。
它遵循来自 clang 的那个:

3:警告:将引用成员 'this_ref' 绑定到临时值 [-Wdangling-field]

哪个编译器是对的?

我会说 GCC 在这种情况下是错误的,并且我正在打开一个问题,但也许它恰恰相反,因为该语言的一个神秘的角落案例。

4

3 回答 3

2

成员声明

A* const& this_ref{this};

绑定对仅在构造函数执行期间存在的临时对象的引用(注意:this是右值表达式)。

我不确定this在那种情况下是否正式可用,但如果是这样,那么使用该指针你就有严重的 UB 情况。

回覆

哪个编译器是对的?

…编译器可以根据需要发出尽可能多的诊断信息。发出诊断书并没有错。因此,根据您的描述,两者都接受代码,那么两个编译器都是正确的(我认为最有可能),或者两者都是错误的。

于 2016-09-12T12:11:45.053 回答
1

此警告的原因是 IMO 摘自标准(12.2.5):

临时绑定到构造函数的 ctor-initializer (12.6.2) 中的引用成员将持续存在,直到构造函数退出。

并且由于关键字 this 是一个纯右值表达式,因此在this_ref初始化期间将创建一个临时对象并this_ref绑定到该临时对象。

但我怀疑您的引用是否实际上是在ctor-initializer.

如果你写:

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

那么您将使用 gcc 重现完全相同的问题,删除 private 也将删除此警告。

据我所知this pointer,可能会在非静态成员函数的主体中使用,我从未读过它可以在默认成员初始化期间用作参数。

于 2016-09-12T13:40:43.240 回答
1

thisprvalue,并且在将引用绑定到 prvalue 时将创建临时对象,因此您将引用成员绑定到默认成员 initializer中的临时对象。

并且将引用成员绑定到默认成员初始化程序中的临时成员是不正确的,标准明确说明了这一点。

$12.6.2/11 初始化基础和成员 [class.base.init]

从默认成员初始化程序绑定到引用成员的临时表达式格式不正确。[ 例子:

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

—结束示例]

并参见CWG 1696,这适用于 C++14。

于 2016-09-12T13:50:31.690 回答