C/C++——赋值理解(匿名临时对象)
对三,王炸:
赋值的本质,是将变量传递给一个匿名临时变量,之后再传递给另一个变量。
- 匿名临时对象:
#include <iostream>
using namespace std; class A {
public:
A() {
cout << "构造函数:" << this << endl;
}
A(const A &a) {
cout << "拷贝构造函数:" << this << endl;
}
~A() {
cout << "析构函数:" << this << endl;
}
}; A f() {
A a;
return a;
}
int main() {
A a = f();
return ;
}
首先要知道赋值的时候回调用拷贝构造函数,初始化的时候调用构造函数:
执行 return a; 产生了匿名临时对象 F903,在给a(外面的)的赋值之前,销毁局部对象F803,F903赋值给了外面的a,程序执行结束时销毁。
A()用来创建匿名对象,理论上这也是应该调用拷贝构造函数的,但事实上,编译器会对此进行优化,变成A a;
那么怎样能避免产生临时对象呢?
直接赋值是不可避免的,但是作为函数返回值时是可以避免的:
当返回类型为引用是,在内存中不产生返回值的副本(注意:不能返回局部变量的引用,局部变量会在函数之前销毁。)
对于这个例子,左边的return ,实际上是调用拷贝构造函数把该对象的值拷入临时对象,再进行return,
return完毕临时对象即刻销毁。对于一般变量亦是如此,只是不调用构造函数。
注意:
- 不要返回函数内部new分配的内存的引用:
正常写法,无内存泄漏。
被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,显然new生成的这块内存将无法释放。
(和上面说的不矛盾,这里直接把*s返回了,不再需要额外的一个临时变量了,但是外面的string s; 已经在栈中分配内存了。)
想要释放掉这片内存,只能这样:
所以说,并不是说返回函数内存new分配的内存的引用或指针是非法的,只是说如果要返回,必须要十分注意,因为很有可能造成内存泄露。
所以一般不提倡返回函数内存new分配的内存的引用或指针。
- 强制类型转化:
C++属于强类型语言,只要类型不一样,就不能赋值。
但是这里是可以赋值当场打脸,也是因为出现了一个匿名临时对象作为隐式转换的过渡桥梁。
注意第二张图:
这里并不是&b开辟了新的空间,引用的就是转换的临时变量。
(int &b = a;是报错的)可见临时变量的常量性,const才能引用。
下面这样的隐式转换看似好像是错的。
#include <iostream>
using namespace std; class A { public:
int x;
A(int num) {
cout << "构造函数:" << this << endl;
x = num;
}
A(const A &a) {
cout << "拷贝构造函数:" << this << endl;
}
~A() {
cout << "析构函数:" << this << endl;
}
}; int main() {
A a = ;
cout << a.x << endl;
return ;
}
两个不同类型能否进行赋值操作,在于能否找到一个中间桥梁,这里的赋值寻找到了构造函数A(int num){};(重载 ‘=’ 运算符也是可以实现的) 所以可以成功,并且a成功实例化。
在构造函数前加上explicit关键字,则禁止 类似这样 不应该允许的经过转换构造函数进行的隐式转换的发生。
加上一个operator int(),反过来也是可以实现的:
C/C++——赋值理解(匿名临时对象)的更多相关文章
- C++中的一类临时对象
类名(参数名)这样的对象是临时对象,不能取地址,不能被引用,不过可以给同类型的其他对象赋值,该临时对象定以后可以进行一次操作,然后立即销毁. 当我们定义一个对象以后并不想立即给它赋初值,而是以后给它赋 ...
- 【编程篇】C++11系列之——临时对象分析
/*C++中返回一个对象时的实现及传说中的右值——临时对象*/ 如下代码: /**********************************************/ class CStuden ...
- 与临时对象的斗争(上)ZZ
C++ 是一门以效率见长的语言(虽然近来越来越多的人“不齿”谈及效率,我深以为不然,在某一次的程序编写中不对效率锱铢必较并不意味意味着我们就不应该追求更多的更好的做法).总之吧,相比起其它语言,程序员 ...
- 认识C++中的临时对象temporary object 分类: C/C++ 2015-05-11 23:20 137人阅读 评论(0) 收藏
C++中临时对象又称无名对象.临时对象主要出现在如下场景. 1.建立一个没有命名的非堆(non-heap)对象,也就是无名对象时,会产生临时对象. Integer inte= Integer(5); ...
- C++中临时对象的学习笔记
http://www.cppblog.com/besterChen/category/9573.html 所属分类: C/C++/STL/boost 在函数调用的时候,无论是参数为对象还是返回一个对 ...
- C++ 临时对象
1.什么是临时对象? swap方法中,常常定义一个temp对象,这个temp对象不是临时对象,而是局部对象.这里所说的临时对象是不可见的,在原代码中是看不到的. 2.为什么会产生临时对象? a.客户期 ...
- 【M19】了解临时对象的来源
1.首先,确认什么是临时对象.在swap方法中,建立一个对象temp,程序员往往把temp称为临时对象.实际上,temp是个局部对象.C++中所谓的临时对象是不可见的,产生一个non-heap对象,并 ...
- [转] C++中临时对象及返回值优化
http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行 ...
- C++ —— 非常量引用不能指向临时对象
目录 举例 分析 解决 1.举例 非常量引用 指向 临时对象 —— 即:将 临时对象 传递给 非常量引用类型. 如以下情况就会出现: 实现实数Rational类,实数可以使用+号相加,运算的结果要可以 ...
随机推荐
- 三:SQL server基础
/一:创建数据库/ use master if exists (select * from sysdatabases where name='数据库名称') drop database 数据库名称 - ...
- webpack执行过程
webpack-cli 执行过程 1.webpack.config.js,shell options参数解析 2.new webpack(options) 3.run() 编译的入口方法 4.comp ...
- 对一些ArcGIS for JS的API的一些理解
1.esri/map map类是每个地图控件中必须引入的类,我们可以通过Map()对地图进行许多的操作,比如修改地图的坐标系.显示级别和初始显示范围等等. Map有一个类型为GraphicsLay ...
- MooseFS安装部署
环境信息 Master服务器 dev04 chunkserver服务器 dev02.dev03.dev04 metalogger服务器 dev03 mount客户端 dev01.dev02 安装前下载 ...
- MAC电脑安装svn客户端cornerstone
个人感觉在mac上最好用的svn客户端就是cornerstone,公司客户端也统一使用这个 sudo spctl --master-disable 这条命令作用就是使得mac运行安装任何来源App,不 ...
- Ionic开发项目
hybrid app是移动开发代替原生开发完成app应用项目的一种方案,Ionic是hybrid app开发的一种选择.对ionic有兴趣可以去网上找相应的基础知识来学习了解,因为Ionic是基于An ...
- ssh key生成步骤
1. 安装git,从程序目录打开 "Git Bash" ,或者直接用git shell,github自带的工具 2. 键入命令:ssh-keygen -t rsa -C " ...
- 高级mask应用
高级mask应用 用mask做遮罩可以实现复杂的效果: 用来形成遮罩的图片: 原始图片: 如果你熟悉Photoshop,那这种效果绝对是你的菜,看代码你会秒懂...... // // RootView ...
- Linux crontab命令详解与实例
内容有重复的,不过本着宁多勿少的原则就都看看吧,就当加深印象啦 基本格式 :* * * * * command分 时 日 月 周 命令 第1列表示分钟1-59 每分钟用*或者 */1表示第2列表示小时 ...
- MVC中使用EF的技巧集(二)——分部验证
1.从数据库生成模型后,再次更新模型时,之前设置的验证规则会丢失. 解决方法:在Models文件夹中新建一个空白类,把它命名为shujuyanzh.cs(类名可以自定),然后把Models中自动生成的 ...