正在通过const-ref未定义的行为捕获新构造的对象
Is capturing a newly constructed object by const ref undefined behavior
以下(人为的例子(可以吗?还是它是未定义的行为:
// undefined behavior?
const auto& c = SomeClass{};
// use c in code later
const auto& v = c.GetSomeVariable();
它是安全的。Const-ref延长了临时的使用寿命。该范围将是const参考的范围
临时对象的生存期可以通过绑定到常量左值引用或右值引用(从C++11开始(,请参阅有关详细信息,请参阅初始化。
引用绑定到临时对象或子对象时其中,临时的寿命被延长以匹配引用的生存期,以下例外:
- return语句中函数返回值的临时绑定没有扩展:它在返回表达式。这样的函数总是返回一个悬空参考
- 到构造函数初始值设定项列表中引用成员的临时绑定仅持续到构造函数退出,而不是只要对象存在。(注意:这种初始化是错误的,如DR 1696(
- 函数调用中引用参数的临时绑定一直存在,直到包含该函数的完整表达式结束调用:如果函数返回一个引用,则该引用将超过完整的表达式,它就变成了一个悬空的引用
- 新表达式中使用的初始值设定项中引用的临时绑定一直存在,直到包含新表达式,而不是初始化对象那么长。如果初始化的对象的寿命超过其引用成员的完整表达式成为悬空引用
- 临时绑定到使用直接初始化语法初始化的聚合的引用元素中的引用(括号(与列表初始化语法相反(大括号(一直存在到末尾包含初始值设定项的完整表达式的。
struct A { int&& r; }; A a1{7}; // OK, lifetime is extended A a2(7); // well-formed, but dangling reference
通常,临时的生命周期不能通过"传递"来进一步延长on":第二个引用,从临时绑定,不影响其使用寿命。
正如@Konrad Rudolph所指出的(见上文最后一段(:
"如果
c.GetSomeVariable()
返回对本地对象的引用,或者它本身正在延长某个对象的生存期的引用,则生存期延长不会生效">
由于寿命延长,这里应该没有问题。新构建的对象将一直存在,直到引用超出范围。
是的,这是完全安全的:绑定到const
引用将临时的生存期延长到该引用的范围。
请注意,行为不是传递性。例如,使用
const auto& cc = []{
const auto& c = SomeClass{};
return c;
}();
cc
悬挂。
这是安全的
[class.temporary]/5
:有三种上下文中,临时性在与完整表达式结尾不同的点被销毁[..]
[class.temporary]/6
:第三个上下文是当引用绑定到临时对象时引用所绑定的临时对象或引用所绑定子对象的完整对象的临时对象在引用的生存期内持续存在,如果引用所绑定到的glvalue是通过以下方法之一获得的:[此处有很多东西]
在这种特定情况下是安全的。然而,请注意,并不是所有临时变量都可以通过常量引用安全捕获。。。例如
#include <stdio.h>
struct Foo {
int member;
Foo() : member(0) {
printf("Constructorn");
}
~Foo() {
printf("Destructorn");
}
const Foo& method() const {
return *this;
}
};
int main() {
{
const Foo& x = Foo{}; // safe
printf("here!n");
}
{
const int& y = Foo{}.member; // safe too (special rule for this)
printf("here (2)!n");
}
{
const Foo& z = Foo{}.method(); // NOT safe
printf("here (3)!n");
}
return 0;
}
为z
获得的引用使用起来不安全,因为在到达printf
语句之前,临时实例将在完整表达式结束时销毁。输出为:
Constructor
here!
Destructor
Constructor
here (2)!
Destructor
Constructor
Destructor
here (3)!
相关文章:
- 构造对象的歧义
- 是什么让放置新调用对象的构造函数?
- 如何从字符串向量构造对象并避免复制?
- 构造对象 c++ (cocos2d-x) 时的区别
- 在特定内存位置构造 c++ 对象
- 在没有堆的情况下用两种方法构造对象
- 如何在构造函数中构造对象并分配引用
- 正在通过const-ref未定义的行为捕获新构造的对象
- C++中有没有一种方法可以通过指定列表中的每个成员变量来构造对象
- 为什么我丢失了这些带有智能指针的构造对象,而不是新的?
- 从 Arduino 中的自定义C++库构造对象时出错
- 在返回语句中构造对象时,std::move() 是否有助于或阻止 RVO?
- 将构造对象但不是构造函数的方法
- 在格式正确的 char 数组中构造对象
- 在C++中构造对象时提供 PV 函数内容
- 如何从常量引用或通过转发模板临时构造对象
- 新构造的对象作为默认模板函数参数
- 访问 vtkActor 构造对象并追加新数据
- C++ 使用放置新的未定义行为构造对象两次
- 初始化现有变量/对象的新构造函数