引用this指针:GCC vs clang

时间:2016-09-12 12:07:04

标签: c++ gcc clang language-lawyer this-pointer

这是对these questions的跟进。

请考虑以下代码:

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

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

如果使用-Wextra进行汇编,则GCC 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]

哪种编译器是对的?

我会说海湾合作委员会在这种情况下是错的,我正在开启一个问题,但也许它恰恰相反,因为该语言是一个神秘的角落。

3 个答案:

答案 0 :(得分:2)

会员声明

A* const& this_ref{this};

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

我不确定this在该上下文中是否正式可用,但如果是那么使用该指针就会出现严重的UB情况。

RE

  

哪种编译器是对的?

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

答案 1 :(得分:1)

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

  

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

并且自keyword this is a prvalue expression起,在this_ref初始化期间,将创建一个临时文件,并将this_ref绑定到该临时文件。

但我怀疑你的引用是否实际在ctor-initializer初始化。

如果你写:

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

然后你将使用gcc重现完全相同的问题,删除private也会删除此警告。

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

答案 2 :(得分:1)

thisprvalue,绑定对prvalue的引用时会创建temporary object,因此您将引用成员绑定到default member initializer中的临时成员。

默认成员初始值设定项中临时引用成员的临时成员格式不正确,标准明确说明了这一点。

$12.6.2/11 Initializing bases and members [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。