为什么将引用绑定到“this”指针时,GCC 5.3.0会发出警告?

13

这是最简单的示例:

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

GCC 5.3.0警告:

警告:对'A::this_ref'的临时绑定仅在构造函数退出之前持续存在[-Wextra] A() : this_ref(this) {}

this是临时变量吗?什么鬼……MSVC 2015对此保持沉默,在我的情况下通过this_ref->member在构造函数外部引用类成员会得到预期行为(但可能只是未定义行为的例子,我不确定)。


编辑:

请注意,此问题扩展了一个链接的可能重复问题,因为它不是关于创建此类引用的通用问题,而是涉及创建此类引用时GCC(和可能的其他编译器,而非MSVC)产生的警告。


由于this仅在构造函数运行时存在,然后停止存在,因此它是临时的。(这正是警告所告诉您的。) - David Schwartz
你能够获取this的地址吗?我认为不行。如果引用没有地址,你如何期望引用能够工作呢? - n. m.
@skypjack 我想两个问题都是由于对this指针的误解而引起的,但是“是否可能获得引用…”在阅读评论之前毫无意义,在阅读评论之后也几乎没有意义。此外,这个问题询问了一个特定编译器版本中的特定警告,而链接的问题则相当于“我正在尝试使用C++11功能替换一个奇怪的Perl式重命名宏,因为某些原因。” - Kyle Strand
@KyleStrand,你最好阅读一下链接问题的答案。无论如何,我不需要说服你做任何事情。我投票将其关闭为重复问题,这是我的个人意见和责任,所以... - skypjack
it is not duplicate @skypjack - Amit Vaghela
2个回答

18

你正在创建一个悬空引用。你的代码与这个代码并无二异:

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

并不存在一个名为this的“对象”。this是一个关键字,当作为表达式使用时,它是一个prvalue(临时对象),其中包含当前实例的地址。

以下是另一个创建类似悬空引用的示例,其看起来像一个对象但实际上并不是:

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

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

在这里,a 是一个命名实体(lvalue),但在r的初始化器中,表达式 a 是一个 prvalue(即数组退化的结果)。

总体信息是,你应该小心使用语言特性,允许 const lvalue 引用绑定到 rvalue。它的主要目的是使函数调用变得容易,但其它用途更为复杂。


5

这是一个临时变量吗?

准确的说,this 不是一个临时变量,但在这里会创建一个临时变量。

首先,this 是一个prvalue

以下表达式都是 prvalue 表达式:

其次,当将引用绑定到一个 prvalue 时,会创建临时对象

临时对象是在以下情况下被创建的:当 prvalue 被实例化以便它可以作为 glvalue 使用时(自 C++17 起),具体如下:

这就是 GCC 发出警告的原因,因为 this_ref 与一个创建的临时变量绑定。 (然后稍后失效,导致 UB。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接