C++真正所谓的暂时对象是不可见的——不会在你的源码中出现。仅仅要你产生一个non-heap object而没有为它命名,便诞生了一个暂时对象。此等匿名对象通常发生于两种情况:

一是当隐式类型转换(implicit type conversions)被施行起来以求函数调用可以成功。

二是当函数返回对象的时候;

其实另一种情况就是当你建立一个non-heap object对象,也就是无名对象的时候。

这里举一个常见的easy忽视的错误:

#include <iostream>

using namespace std;

int main(int argc, char *argv[]) {
string s1("a"),s2("b");
const char * s = (s1+s2).c_str();
printf("%s\n",s);
}

这个程序执行的时候你可能会得到正确的结果,但其实这里的做法是不安全的,s1+s2产生的暂时对象会在表达式的结尾被析构。所以假设跟踪堆栈会发如今print语句中s的内存空间已经指向未知地址了。

这里针对3种会产生暂时对象的情况举例进行说明:

1.隐式类型转换

void uppercasify(string& str);

// changes all chars in str to upper case
char subtleBookPlug[] = "Effective C++";
uppercasify(subtleBookPlug); //error!!!

由于要使函数调用成功,必须将subtleBookPlug转换成string类型,而编译器觉得你要改变的subtleBookPlug。而类型转换后将产生一个类型为string的暂时对象,而在void uppercasify(string& str)中。被改变的将是这个暂时对象,而不是subtleBookPlug,这显然不是程序猿所期望的。所以C++明智地禁止了这样的行为

2.函数返回对象

#include <iostream>

using namespace std;

int func() {
int itgr;
return itgr;
} int main(int argc, char *argv[]) {
int in;
in = func();
}

函数中的返回值会以值拷贝的形式复制到被调用函数栈中的一个暂时对象。这里表达式func()创建了一个暂时对象。用来存储func()函数返回的对象,暂时对象由func()返回的itgr对象拷贝构造。暂时对象赋值给in后,赋值表达式结束,暂时对象被析构。所以这里就有一个问题。

int& intref = func();

假设用一个暂时对象去初始化intref引用,一旦该表达式执行结束,暂时对象的生命周期也就结束了。引用的实体已经不复存在。

3.no heap的对象

int& intref = int(5);
int itgr = int(5);
Calculate(int(5));

上述表达式中的暂时对象用来完毕初始化引用。拷贝构造和实參等作用。

关于暂时对象生命周期的延长等问题,后面的博客再更新吧。越来越觉得C++真心麻烦…

C++暂时对象的更多相关文章

  1. Python-面向对象 (二 继承)

    一 继承   基类定义例如以下: class people:     #define attribute     name = ''     age  = 0     #define private ...

  2. hibernate中持久化对象的生命周期(三态:自由态,持久态,游离态 之间的转换)

    三态的基本概念: 1,  暂时状态(Transient):也叫自由态,仅仅存在于内存中,而在数据库中没有对应数据.用new创建的对象,它没有持久化,没有处于Session中,处于此状态的对象叫暂时对象 ...

  3. C++ Primer 学习笔记_62_重载操作符与转换 --调用操作符和函数对象

    重载操作符与转换 --调用操作符和函数对象 引言: 能够为类类型的对象重载函数调用操作符:一般为表示操作的类重载调用操作符! struct absInt { int operator() (int v ...

  4. Effective C++:条款28:避免返回 handles 指向对象内部成员

    (一) 有时候为了让一个对象尽量小,能够把数据放在另外一个辅助的struct中,然后再让一个类去指向它.看以下的代码: class Point { public: Point(int x, int y ...

  5. C++生产和使用的临时对象

     所谓暂时对象就是一种无名对象. 它的出现假设不在程序猿的预期之下(比如不论什么pass by value操作都会引发copy操作,于是形成一个暂时对象),往往照成效率上的负担. 但有时候能够制造 ...

  6. hibernate在持久对象的生命周期(三州:自由状态,持久状态,自由状态 之间的转换)

    三种状态的基本概念: 1.  临时身份(Transient):也被称为自由状态,它只存在于内存中,并且在数据库中没有相应的数据. 使用new创建的对象,久化,没有处于Session中,处于此状态的对象 ...

  7. 切勿创建包括auto_ptr的容器对象

     当你拷贝一个auto_ptr时,它所指向的对象的全部权被移交到拷入的auto_ptr上,而它自身被置为NULL.我的理解是:拷贝一个auto_ptr意味着改变它的值.比如: auto_ptr&l ...

  8. Java 并发编程(二)对象的公布逸出和线程封闭

    对象的公布与逸出 "公布(Publish)"一个对象是指使对象可以在当前作用域之外的代码中使用.可以通过 公有静态变量.非私有方法.构造方法内隐含引用 三种方式. 假设对象构造完毕 ...

  9. Java中对象与引用

    初学Java 时.在非常长一段时间里,总认为基本概念非常模糊. 后来才知道.在很多Java 书中.把对象和对象的引用混为一谈. 假设分不清对象与对象引用,那实在没法非常好地理解以下的面向对象技术.把自 ...

随机推荐

  1. 阿里云主机和RDS使用心得

    本文上非广告,只是将这近1年的使用过程给大家分享一下. 去年下半年,服务器托管到期,加上服务器也使用了5.6年,严重老化,当时正好看到阿里云的宣传广告,就开始了阿里云使用历程.陆续购买了4台云主机,I ...

  2. java转换字符串编码格式 (解码错误,重新解码)

    字符集概念:规定了某个文字对应的二进制数字存放方式(编码)和某串二进制数值代表了哪个文字(解码)的转换关系. 我们在计算机屏幕上看到的是实体化的文字,而在计算机存储介质中存放的实际是二进制的比特流. ...

  3. java中return和continue区别

    编程语言大多是想通的,当然java也不例外,下面的在其他编程语言也是相同的道理. return与continue的区别 先看代码哦 class demo2 { public static void m ...

  4. 编程获取linux的CPU使用的内存使用情况

    Linux可用下top.ps命令检查当前的cpu.mem用法.下面简单的例子: 一.采用ps查看资源消耗的过程 ps -aux 当您查看进程信息,第三列是CPU入住. [root@localhost ...

  5. 【错排问题】【HDU2048】神、上帝以及老天爷

    神.上帝以及老天爷 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...

  6. WinForm RDLC SubReport Step by step

    最近在做的一个PO管理系统,因为要用到订单打印,没有用水晶报表,直接使用VS2010的Reporting.参考了网上的一些文章,但因为找到的数据是用于WebForm的,适配到WinForm有点区别,竟 ...

  7. .net 链接oracle

    虽然EF6都快要出来了,但是对于Oracle数据库,仍然只能用DB first和Model First来编程,不能用Code First真是一个很大的遗憾啊. 好了,废话少说,我们来看看EF中是如何用 ...

  8. Alter的用法(添加字段,删除字段,修改字段名)

    1.在表emp中新增字段sexy(性别) alter table emp add sexy varchar2(2); 新增多个字段cxx 和shoneworn alter table emp add  ...

  9. Follow-up letter to information seeking meeting, e-mail version

      Subject: (logical to recipient!) Thank you for meeting Tuesday, Nov. 23 November 26, 20XY Mr. Jame ...

  10. 通过递归方法对一个单词所有的组合进行列举(java)

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public ...