请考虑以下代码:
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]
哪种编译器是对的?
我会说海湾合作委员会在这种情况下是错的,我正在开启一个问题,但也许它恰恰相反,因为该语言是一个神秘的角落。
答案 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)
this
为prvalue,绑定对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。