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. C++星号的含义

    [转载] [http://blog.sina.com.cn/s/blog_4a50d85b0100uk3c.html]   1.乘法运算符   2.定义指针 int *p = 0; 还是 int* p ...

  2. MATLAB技巧—sort和sortrows函数

    MATLAB技巧-sort和sortrows函数 1.sort函数 sort函数用于对数据进行排序,通过help sort命令,可以查找到sort函数的具体用法: Y = SORT(X,DIM,MOD ...

  3. PAT甲级——A1047 Student List for Course

    Zhejiang University has 40,000 students and provides 2,500 courses. Now given the registered course ...

  4. jQuery同步/异步调用后台方法

    $.ajax({ type: "Post", url: "UserManage.aspx/SubmitPage",//页面/方法名 data: "{' ...

  5. Hadoop Serialization -- hadoop序列化详解 (2)【Text,BytesWritable,NullWritable】

    回顾: 回顾序列化,其实原书的结构很清晰,我截图给出书中的章节结构: 序列化最主要的,最底层的是实现writable接口,wiritable规定读和写的游戏规则 (void write(DataOut ...

  6. Layui 获取表单提交数据

    HTML<div class="layui-card-header layuiadmin-card-header-auto"> <form class=" ...

  7. PHP与RBAC设计思路讲解与源码

    在说权限管理前,应该先知道权限管理要有哪些功能: (1).用户只能访问,指定的控制器,指定的方法 (2).用户可以存在于多个用户组里 (3).用户组可以选择,指定的控制器,指定的方法 (4).可以添加 ...

  8. 英特尔人工智能圆桌论坛举行 四位大咖论道AI

    英特尔人工智能圆桌论坛举行 四位大咖论道AI 2017-04-01 17:57     北京2017年4月1日电 /美通社/ -- 毫无疑问,人工智能已是最具变革力的发展趋势之一,在3月31日举行的2 ...

  9. centos部分网站无法访问问题的解决

    CentOS 5内核对TCP的读缓冲区大小有缺省设置,缺省为:net.ipv4.tcp_rmem = 4096 87380 4194304 解决办法就是将最后一个数字改小一点,具体操作就是在文件/et ...

  10. Django项目:CRM(客户关系管理系统)--16--08PerfectCRM实现King_admin显示注册表的字段表头

    # king_urls.py # ————————02PerfectCRM创建ADMIN页面———————— from django.conf.urls import url from king_ad ...