class Test{
public:
Test(int a):m_int(a){
printf("this is Test(%d) ctor\n", m_int);
}
~Test(){
printf("this is Test(%d) dtor\n", m_int);
}
const Test & testfun() const{
printf("this is %d testfun\n", m_int);
return *this;
}
private:
int m_int;
}; struct S {
int mi;
const Test& mt;
~S(){
printf("this is S dtor\n");
}
};

Whenever a reference is bound to a temporary or to a subobject thereof, the lifetime of the temporary is extended to match the lifetime of the reference, with the following exceptions:

当临时对象绑定到引用上时,临时对象的生命期也会跟随引用的生命期而得到延长,但是也有一些特殊情况:

a temporary bound to a return value of a function in a return statement is not extended: it is destroyed immediately at the end of the return expression. Such function always returns a dangling reference.

对于返回引用的函数,如果函数中的return语句返回的是一个临时对象,则该临时对象在return语句的最后就会被销毁。这种情况下,该函数返回的引用实际上就是个“空悬引用”(dangling reference)。实际上即使不是临时对象,只要是返回函数内部对象的引用,在return之后,该引用就是空悬引用了:

const Test & fun(){
return Test();
} int main(int argc, char **argv){
const Test &aa = fun();
printf("over\n");
aa.testfun();
}

上面的代码,在编译时就会报警:warning: returning reference to temporary [-Wreturn-local-addr]  return Test(3);

代码结果如下:

this is Test() ctor
this is Test() dtor
over
Segmentation fault (core dumped)

实际上,最后的段错误有可能发生,也有可能不发生,重要的是,const Test &aa = fun();之后,aa已经是个空悬引用了。

a temporary bound to a reference member in a constructor initializer list persists only until the constructor exits, not as long as the object exists. (note: such initialization is ill-formed as of DR 1696).  (until C++14)

在initializer list形式的构造函数中,如果临时对象绑定到一个对象A的引用成员中,则该临时对象的生命期在构造函数结束后就会结束,并不跟随对象A的生命期而得到延长。但是这一条规则在C++14之后就不再使用了。下面的代码验证了这一点:

    S ss {, Test() };
printf("over\n");
ss.mt.testfun();

代码的结果如下:

this is Test() ctor
over
this is testfun
this is Test() dtor
this is S dtor

可见,S中的引用成员mt绑定到了一个临时对象,该临时对象的生命期跟随ss而得到了延长。

a temporary bound to a reference parameter in a function call exists until the end of the full expression containing that function call: if the function returns a reference, which outlives the full expression, it becomes a dangling reference.

如果函数参数为引用,当临时对象绑定到该参数上时,其生命期一直持续到包含该函数调用的表达式的结束,如果该函数又返回了该引用,则该引用成为空悬引用:

const Test & fun3(const Test &a){
a.testfun();
return a;
} int main(int argc, char **argv){
const Test &a = fun3(Test()).testfun();
printf("over\n");
a.testfun();
}

代价结果如下:

this is Test() ctor
this is testfun
this is testfun
this is Test() dtor
over
this is testfun

尽管最后的testfun打印出了结果,但是这是未定义行为。

a temporary bound to a reference in the initializer used in a new-expression exists until the end of the full expression containing that new-expression, not as long as the initialized object. If the initialized object outlives the full expression, its reference member becomes a dangling reference.

如果临时对象绑定到了一个在new表达式中初始化的引用,则该临时对象的生命期一直持续到包含new的表达式的结束,而不是跟随new出来的对象的生命期而得到延长,此时,该对象中的引用成员在表达式结束之后,就成了空悬引用:

    S *p = new S{, Test() };
printf("p->mi is %d\n", p->mi);
p->mt.testfun();

代码结果如下:

this is Test() ctor
this is Test() dtor
over
p->mi is
this is testfun

尽管最后的testfun打印出了结果,但是这是未定义行为。

In general, the lifetime of a temporary cannot be further extended by "passing it on": a second reference, initialized from the reference to which the temporary was bound, does not affect its lifetime.

一般而言,临时对象的生命期并不能随着引用的传递而得到延长:如果临时对象绑定到了引用A,而使用引用A又初始化了引用B,这种情况下,引用B对临时对象的生命周期没有影响。

https://en.cppreference.com/w/cpp/language/reference_initialization

C++临时对象的生命期的更多相关文章

  1. C++中的临时对象

    1,临时对象神秘在于不知不觉就请入程序当中,并且给程序带来了一定的问题: 2,下面的程序输出什么?为什么? #include <stdio.h> class Test { int mi; ...

  2. 11.C++-临时对象分析

    首先来参考以下代码: #include <stdio.h> class Test { int mi; public: Test(int i) { mi = i; } Test() { Te ...

  3. C++解析(13):临时对象与const对象

    0.目录 1.临时对象 2.const对象 3.类成员 4.小结 1.临时对象 一个有趣的问题--下面的程序输出什么?为什么? #include <stdio.h> class Test ...

  4. 二十一、C++中的临时对象

    思考: 构造函数是一个特殊的函数 是否可以直接调用? 是否可以在构造函数中调用构造函数? 直接调用构造函数的行为是什么? 答: 直接调用构造函数将产生一个临时对象 临时对象的生命周期只有一条语句的时间 ...

  5. C++ 对象构造顺序、构析函数、临时对象。

    对象的构造顺序: 1.对于局部对象,构造顺序是根据程序执行流进行构造,从上到下. #include <stdio.h> class Test { int mi; public: Test( ...

  6. STL——临时对象的产生与运用

    所谓临时对象,就是一种无名对象.它的出现如果不在程序员的预期之下(例如任何pass by value操作都会引发copy操作,于是形成一个临时对象),往往造成效率上的负担.但有时候刻意制造一些临时对象 ...

  7. [转] C++中临时对象及返回值优化

    http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行 ...

  8. C++ —— 非常量引用不能指向临时对象

    目录 举例 分析 解决 1.举例 非常量引用 指向 临时对象 —— 即:将 临时对象 传递给 非常量引用类型. 如以下情况就会出现: 实现实数Rational类,实数可以使用+号相加,运算的结果要可以 ...

  9. 与临时对象的斗争(上)ZZ

    C++ 是一门以效率见长的语言(虽然近来越来越多的人“不齿”谈及效率,我深以为不然,在某一次的程序编写中不对效率锱铢必较并不意味意味着我们就不应该追求更多的更好的做法).总之吧,相比起其它语言,程序员 ...

随机推荐

  1. 新增对象Products 的流程说明

    库内新增对象Products 的流程说明: 第一步: com.jeecms.cms.entity.assist.base下建立模型基础类,BaseCmsProducts.java com.jeecms ...

  2. Eureka Instance实例信息配置

    Eureka包含四个部分的配置 instance:当前Eureka Instance实例信息配置 client:Eureka Client客户端特性配置 server:Eureka Server注册中 ...

  3. 在scrapy中利用Selector来提取数据

    1.创建对象 Selector类的实现位于scrapy.selector模块,创建Selector对象的时候,可以将页面的Html文档字符串传递给Selector构造器方法 2.选中数据 调用Sele ...

  4. jQuery Validate扩展验证方法 (zhangxiaobin)

    /***************************************************************** jQuery Validate扩展验证方法 (zhangxiaob ...

  5. hadooplinux服务连接window平台问题

    window eclipse下有hadoop 服务插件可以安装方便开发,今天突然发现连接不上做测试,鼓捣了一下.大多是因为端口问题 9000是DFS端口 50020是IPC服务端口,50070是web ...

  6. Mybatis编写初始化Dao代码

    第一步:创建User实体类(POJO) package com.xu.pojo; import java.util.Date; /** * * @author 徐亮亮 * Title: User * ...

  7. JAVA面试常见问题之进程和线程篇

    1.线程和进程的概念.并行和并发的概念 进程:计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本 ...

  8. 【python之路29】python生成器generator与迭代器

    一.python生成器 python生成器原理: 只要函数中存在yield,则函数就变为生成器函数 #!usr/bin/env python # -*- coding:utf-8 -*- def xr ...

  9. 用JetBrains PyCharm 2017.2创建运行Django程序

    在JetBrains PyCharm 2017.2里选择 文件(F) 新项目 点击  三角形  运行 修改Urls.py """S14Djngo URL Configur ...

  10. 数据库安全 (ch.4)

    4.2.4 授权与回收 使用 Grant 授予权限 使用Revoke 回收权限 Grant [权限] ON *.. to * [with grant option] with grant option ...