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

最新文章

  1. 【转】搞清FastCgi与PHP-fpm之间的关系
  2. 通过反射获取DLL的类实现加载窗体
  3. ASP.NET Core 使用 Redis 和 Protobuf 进行 Session 缓存
  4. 【精粹系列】PHP精粹
  5. 利用 filter 机制 给 静态资源 url 加上时间戳,来防止js和css文件的缓存,利于开发调试
  6. 基于jquery上的轻量级《数据模板解析》插件
  7. Winform Textbox MultiLine和WordWrap属性的使用
  8. jsp内置对象作业1-用户登录
  9. Spring @Service生成bean名称的规则
  10. 使用MediaPlayer和SurfaceView播放视频
  11. Apache Ant运行时Unable to locate tools.jar解决方法
  12. 常量折叠 const folding
  13. [置顶] cocos2d-x 3.0游戏开发xcode5帅印博客教学 003.[HoldTail]游戏世界以及背景画面
  14. HDU/HDOJ 2612 Find a way 双向BFS
  15. Android Wear和二维码
  16. DevExpress 控件使用之GridControl基本属性设置
  17. Flask-Moment----探索
  18. vue小白快速入门
  19. jmeter 多个sql写在一个jdbc请求中注意事项
  20. JavaScript(二)

热门文章

  1. 深入浅出 Java Concurrency (19): 并发容器 part 4 并发队列与Queue简介[转]
  2. 深入浅出 Java Concurrency (5): 原子操作 part 4[转]
  3. jeecms 修改后台访问路径
  4. vue 路由入门(vue-router)
  5. Leetcode221. Maximal Square最大正方形
  6. c++设计模式:策略模式
  7. Windows 禁用Windows updata服务
  8. 【笔记】LR11中关联设置
  9. C++使用stringstream分割字符串
  10. mysql8 navicat