【问题标题】:Reference to the this pointer: GCC vs clang引用this指针:GCC vs clang
【发布时间】:2016-09-12 12:07:04
【问题描述】:

这是thesequestions的后续。

考虑以下代码:

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]

哪个编译器是正确的?

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

【问题讨论】:

  • 这两个例子看起来是一样的。你也没有提出警告。
  • @Cheersandhth.-Alf 区别是private:。但显示实际警告确实很好。
  • @Cheersandhth.-Alf private 的示例有所不同,我将为您添加警告确实是正确的。
  • 真正奇怪的是它连接了语言的两个不相关的部分。 private: 是名称查找限制,这里适用于this_ref 的名称查找。临时值为this,但它不用于必须查找名称this_ref 的上下文中。
  • @skypjack:欧洲键盘布局,反引号 ` 也用于在元音上放置重音符号。例如。一种。但现在修好了。

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


【解决方案1】:

成员声明

A* const& this_ref{this};

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

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

回复

哪个编译器是对的?

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

【讨论】:

  • 在一种情况下它们都发出警告,但在另一种情况下则不发出警告。我可以接受诊断是免费的,但至少这里缺乏连贯性。
【解决方案2】:

此警告的原因是 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 可能用于非静态成员函数的主体中,我从未读过它可以用作默认成员初始化期间的参数。

【讨论】:

    【解决方案3】:

    thisprvalue,并且temporary object 将在将引用绑定到prvalue 时创建,因此您将引用成员绑定到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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-12
      • 1970-01-01
      • 1970-01-01
      • 2015-12-31
      • 2020-06-12
      • 2021-04-18
      • 2013-08-21
      相关资源
      最近更新 更多