C++对象模型9——临时对象的生命周期、模板及实例化分析、内联函数
一、临时对象的生命周期
T c=a+b
假设T是一个类型,那么上述代码执行时,首先会产生一个临时对象用来存放a+b的结果(拷贝初始化临时对象),然后用该临时对象拷贝初始化c,最后临时对象被释放。如果开启编译器优化选项,那么会直接用a+b的结果初始化c
临时性对象被销毁的时机应该是对表达式求值过程中的最后一个步骤。
比如下面的代码
int main()
{string s1="123";string s2="qwe";bool flag;cin>>flag;string res=flag?s1+s2:"";return 0;
}
上述代码中保存s1+s2的临时对象并不会马上被销毁,而是等res初始化完成后才被销毁
下面这段代码输出的p是无效值,但是经过测试后,发现并不是(我也整不明白为啥了。。。)
int main()
{string s1="123";string s2="qwe";const char *p=(s1+s2).c_str();cout<<p<<endl;return 0;
}
此外,如果一个临时对象和引用绑定,那么,临时对象的生命周期将会被提升,直到被初始化的引用的生命周期结束
示例见https://blog.csdn.net/Master_Cui/article/details/106353580
二、模板及实例化分析
2.1、函数模板、类模板及其实例化
template<class T>
T funadd(const T& a, const T& b)
{T addhe = a + b;return addhe;
}int main()
{return 0;
}
上述代码没有调用函数模板,对应的反汇编代码中,可以发现,没有找到funadd的代码,而且,在网站https://godbolt.org/上试验,如果一个模板函数没有被实例化,那么将不会产生汇编代码
因为没有调用函数模板,所以,没有实参推断和实例化的过程,所以在可执行文件中也就不会有相应的代码产生,这么做的目的是为了防止因为代码膨胀导致可执行文件过大
当调用了funcadd后
可见,实例化之后,编译器才会产生对应的代码。
上述机制同样适合类模板及类模板中的非虚成员函数
如果定义了一个模板类的指针,那么也不会产生实际的类对象的代码,因为指针指向的内容可以无效,这就是为什么声明了一个不完整的类后,可以声明相应的指针,因为指针只是内置类型,指向的数据不保证有效
上述机制有个例外,那就是模板类中的虚函数
示例
template<class T>
class ATPL
{
public:virtual void func1() { cout << "ATPL::func1()" << endl; }
};int main()
{ATPL<int> t;return 0;
}
上述代码虽然没有使用func1,但是编译器依然会为其产生代码,因为要将该函数的地址放到虚表中,所以不得不产生代码
三、内联函数
inline只是个请求,如果这项请求被接受,编译器就认为它可以用一个表达式将函数展开。
处理一个inline函数,有两个阶段:1.分析函数定义内容。如果函数因其复杂度或建构问题,被判断不可成为inline,它会被转为一个static函数,并在产生对应的函数定义。2.如果可以inline,那么在调用点上,函数会进行扩展操作。如果内联函数被展开为表达式的次数太多,会产生过多的代码,导致程序内存上升。如果编译器把一个函数内联,那么也有可能会因为接受函数参数而产生一些临时变量,也会
通过网站https://godbolt.org/可知,内联函数如果被编译器内联优化,并不会产生反汇编代码
但是上述代码的在没有开启优化选项时的反汇编代码如下
可见,并没有进行汇编优化,因为依然跳转到函数栈帧进行函数调用,如果想让编译器进行内联优化,需要添加-O开启优化选项
g++ -g -O -fno-elide-constructors -Wall c++model.cpp
此时的反汇编代码如下
此时在文件中已经查不到add_inline的调用,说明add_inline已经被内联优化了
参考
《深度探索C++对象模型》
《C++新经典:对象模型》
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出
C++对象模型9——临时对象的生命周期、模板及实例化分析、内联函数相关推荐
- java 对象 jvm生命_JVM对象的生命周期
一旦一个类被装载.连接和初始化,它就随时可以被使用.程序可以访问它的静态字段,调用它的静态方法,或者创建它的实例.作为Java程序员有必要了解Java对象的生命周期. 类实例化 在Java程序中,类可 ...
- 面试:对象的生命周期
面试:对象的生命周期 一旦一个类被装载.连接和初始化,它就随时可以被使用.程序可以访问它的静态字段,调用它的静态方法,或者创建它的实例.作为Java程序员有必要了解Java对象的生命周期. 类实例化 ...
- java对象什么时候回收_Java对象的生命周期与垃圾回收以及四种引用
创建对象的方式用new语句创建对象. 使用反射,调用java.lang.Class或java.lang.reflect.Constructor的newInstance()实例方法. 调用对象的clon ...
- Java 对象的生命周期
Java对象的生命周期 在Java中,对象的生命周期包括以下几个阶段: 创建阶段(Created) 应用阶段(In Use) 不可见阶段(Invisible) 不可达阶段(Unreachable) 收 ...
- Hibernate学习(4)- Hibernate对象的生命周期
1.Hibernate对象的生命周期(瞬时状态.持久化状态.游离状态) 1.瞬时状态(Transient): 使用new操作符初始化的对象就是瞬时状态,没有跟任何数据库数据相关联: 2.持久化状态(P ...
- Java对象的生命周期与作用域的讨论(转)
导读: Java对象的生命周期大致包括三个阶段:对象的创建,对象的使用,对象的清除.因此,对象的生命周期长度可用如下的表达式表示:T = T1 + T2 +T3.其中T1表示对象的创建时间,T2表示对 ...
- 把对象的创建交给spring来管理—— 1.创建bean的三种方式 2.bean对象的作用范围 3.bean对象的生命周期
把对象的创建交给spring来管理 spring对bean的管理细节 1.创建bean的三种方式 2.bean对象的作用范围 3.bean对象的生命周期 创建Bean的三种方式 ...
- java对象的生命周期及回收
在网上看到一篇不错的文章,记录下来备忘. 要理解java对象的生命周期,我们需要要明白两个问题, 1.java是怎么分配内存的 ,2.java是怎么回收内存的. 喜欢java的人,往往因为它的内存自动 ...
- MyBatis 实际使用案例-核心对象的生命周期
在编程式使用的这个demo 里面,我们看到了MyBatis 里面的几个核心对象:SqlSessionFactoryBuiler.SqlSessionFactory.SqlSession 和Mapper ...
最新文章
- 10.2.2移动产品离线功能等具体解释----暨4月8日移动《在离线一体化》公开课Qamp;A...
- Windows上erl.exe的CPU使用率很高的问题【未解决】
- OpenAI不Open:闭门造车、融资不断,深度报道再掀争议,马斯克:应该更加开放...
- 处理json中影响解析的多余引号
- “马踏飞”AI机器人实现方案介绍
- 北大清华团队编写!200多个科学实验+视频,和爸爸一起在家做
- Python 包管理之 poetry
- LinkedList作者说他自己都不用LinkedList?看完给我整不会了。。
- 【STM32】【STM32CubeMX】STM32CubeMX的使用之二:外部中断
- getopt函数应用
- 苏州大学计算机考研资料汇总
- SpringMVC-狂神笔记
- php同步登录,使用ucenter实现多站点同步登录的讲解
- 草履虫纳米机器人_《Nature》草履虫大小的微型机器人:由激光驱动可用于显微外科...
- Java中文分词组件 - word分词(skycto JEEditor)
- 【Chrome-crx】键盘模拟鼠标点击网页按钮
- html5 promise,从HTML5与PromiseA+规范来看事件循环
- 云存储:对象存储管理与安全
- 牛津书虫系列102册1.27G书虫配套6.8G MP3 百度网盘下载
- We7网站群的共享机制