修改临时对象
Modyfying temporary object
有人能说出为什么test(2)
对象在调用后被销毁test_method()
吗?
#include<iostream>
#include<string>
using namespace std;
class test
{
int n;
public:
test(int n) : n(n)
{
cout << "test: " << n << endl;
}
~test()
{
cout << "~test: " << n << endl;
}
test & test_method()
{
cout << "test_method: " << n << endl;
return *this;
}
};
int main(int argc, const char *argv[])
{
cout << "main start" << endl;
const test &test1 = test(1);
const test &test2 = test(2).test_method();
cout << "main end" << endl;
}
输出为:
main start
test: 1
test: 2
test_method: 2
~test: 2
main end
~test: 1
test(2).test_method()
返回一个引用,该引用绑定到test2
,然后它引用的对象在完整表达式的末尾被销毁,因为它是一个临时对象。这应该不足为奇。
真正令人惊讶的是,test1
仍然是一个有效的引用,因为它直接绑定到临时引用,并且将临时引用绑定到引用会将临时的生存期延长到引用变量的生存期。
您只需要注意,在test(2)
情况下,临时对象不绑定到任何东西。它只是用来调用一些成员函数,然后它的工作就完成了。它不"照看"成员函数,换句话说,生命周期延长不是通过所有可能的未来引用传递的。
这里有一个简单的思想实验,为什么实际上不可能有"任意寿命延长":
extern T & get_ref(T &);
{
T const & x = get_ref(T());
// stuff
// Is x still valid?
}
我们不知道x
是否在第一线之后仍然有效。 get_ref
可以做任何事情。如果它实现为 T & get_ref(T & x) { return x; }
,我们可能希望有魔法,但它也可能是这样的:
namespace { T global; }
T & get_ref(T & unused) { return global; }
在原始翻译单元中无法决定是否需要扩展任何内容。因此,该标准目前的方式是,这是一个完全微不足道的本地决定,只是在查看引用声明表达式时做出的,所讨论的临时对象的生存期应该是多少。
因为C++标准需要此行为。 如果希望对象持久化,请为其命名。 它将持续到名称。
编辑:您的示例,test1
是您为第一个对象指定的名称,而第二个对象根本没有获得任何名称,因此它不会超过表达式的计算时间。
相关文章:
- 在不复制临时对象的情况下延长其生存期
- 为什么当我们有常量引用时创建临时对象?
- 程序如何'remember'临时对象?
- 返回对临时对象的引用
- 防止临时对象文件访问 MSVC 中的磁盘
- 是否可以在C++中移动临时对象的属性?
- 通过引用传递临时对象
- 临时C++对象是否为左值?
- 临时对象:术语澄清
- 存储对(可能)临时对象的引用是否合法,只要引用不比对象存活?
- 临时对象有身份吗?
- 临时对象上的运算符重载
- 如何在没有 std::move 的情况下移动临时对象
- 临时对象在C++中是不可避免的吗?
- 编译错误:临时对象构造函数中缺少参数
- 为什么在按值返回时创建临时对象,而不是在按值传递给函数参数时创建临时对象
- 我试图创建临时对象的方式有错误吗
- 子表达式中临时对象的生存期
- C++17:是编译器为(静态存储持续时间)const引用绑定创建的可修改的临时对象(和存储)
- 修改临时对象