下面是一个最小的例子:
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
引用类成员给出了预期的行为(但可能只是UB的情况,不确定)。
编辑:
请注意,这个问题将一个链接扩展为可能的副本,因为它不是关于如何创建这样的引用的通用问题,而是关于在创建一个引用时警告GCC(以及可能的MSVC以外的其他编译器)产生的问题。
您正在创建一个悬空引用。您的代码与以下代码没有什么不同:
struct X
{
const int & r;
X() : r(5) {}
}; // ^^^^ dangles
不存在名为this
的"对象"。this
是一个关键字,当用作表达式时,它是一个包含当前实例地址的右值(临时值)。
下面是另一个例子,从看起来像对象但不是对象的东西创建类似的悬空引用:
struct Y
{
int a[10];
int* const & r;
Y() : r(a) {}
};
这里,a
是一个命名实体(左值),但在r
的初始化式中,表达式 a
是一个右值(即数组衰减的结果)。
总的消息是,您应该小心使用允许const左值引用绑定到右值的语言特性。它的主要目的是简化函数调用,但它的其他用途要复杂得多。
this
是临时的吗?
确切地说,this
不是临时的,但是这里创建了一个临时的。
首先this
是右值,
其次,在将引用绑定到右值时将创建临时对象,下列表达式是右值表达式:
在以下情况下
when a prvalue is materialized so that it can be used as a glvalue, which occurs (since C++17)
创建临时对象:
- 将引用绑定到右值
这就是为什么GCC给出警告,因为this_ref
被绑定到一个临时创建。(然后被悬挂起来,这导致了UB)