1)返回对临时的引用是否是未定义的行为,即使未使用该引用?例如,该程序是否保证输出“好”:
int& func()
{
int i = 5;
return i;
}
int main()
{
func();
cout << "good" << endl;
return 0;
}
2)是否未定义行为只是简单地引用一个不再存在的对象,即使该引用未被使用?例如,该程序是否保证输出“好”:
int main()
{
int *j = new int();
int &k = *j;
delete j;
cout << "good" << endl;
return 0;
}
3)结合这些是不确定的行为?
int& func()
{
int i = 5;
return i;
}
int main()
{
int& p = func();
cout << "good" << endl;
return 0;
}
答案 0 :(得分:6)
2)是否未定义行为只是简单地引用一个不再存在的对象,即使该引用未被使用?
没有。当引用被初始化时,引用必须引用有效对象的规则适用。该规则已在评论中引用:&#34;引用应初始化为引用有效的对象或功能。&#34;在您的程序中没有违反此规则,并且在初始化后要求它们引用有效对象或函数的引用没有其他限制。
该标准有一些涉及悬空引用的例子,例如[class.temporary] 5.4:
struct S { int mi; const std::pair<int,int>& mp; }; S a { 1, {2,3} }; S* p = new S{ 1, {2,3} }; // Creates dangling reference.
并且没有说任何这样的例子,仅仅存在悬空参考是无效的。虽然它从未明确表示允许,但没有任何禁止它的规则就足以允许它。
1)返回对临时的引用是不确定的行为,即使没有使用该引用?
没有。结果的构造(引用的初始化)发生在被调用函数的上下文中。在构造结果之后运行的被调用函数中甚至可以有额外的代码:本地对象的析构函数在结果构造完成后运行。由于引用已初始化为有效对象,这就像您的第二个问题一样,相同的规则仍然没有被违反。
3)结合这些是不确定的行为?
是。在您的示例中,p
未初始化为引用有效对象或函数。从您对问题的评论中可以看出,标准中的措辞存在问题,但该规则的目的非常明确,如果违反该规则,则行为未定义。
答案 1 :(得分:5)
我没有看到任何禁止案例1和2的规则,也没有找到相关的缺陷报告。
我们从C ++标准草案中得到的全部内容来自8.3.2
[dcl.ref] 部分:
[...]引用应初始化为引用有效对象或 功能。 [注意:特别是,一个明确定义的程序中不能存在空引用,因为唯一的方法 创建这样的引用将是绑定到通过空指针间接获得的“对象”, 导致未定义的行为。[...]
不适用于案例1,因为我们没有初始化引用,因为当我们初始化引用时,对象有效,因此两者都没有。
这似乎适用于案例3.那么有效对象意味着什么是以下缺陷报告的主题。涵盖这个主题的缺陷报告仍然是开放的,因此我们只能了解当前的想法,即这应该是未定义的行为。
如果我们查看defect report 453: References may only bind to “valid” objects ,它会处理绑定对无效对象的引用的含义。目前提出的决议案如下:
[...]如果引用直接绑定到的左值既不指定现有对象或适当类型的函数(8.5.3 [dcl.init.ref]),也不指定适当大小的存储区域和对齐以包含引用类型的对象(1.8 [intro.object],3.8 [basic.life],3.9 [basic.types]),行为未定义。 [...]
所以我们可以说当前的想法是,这应该是未定义的行为,但目前这是缺陷,所以我们不能肯定地说这个缺陷报告得到解决。我会谨慎行事并假设它是未定义的行为。