思考:

构造函数是一个特殊的函数

  • 是否可以直接调用?
  • 是否可以在构造函数中调用构造函数?
  • 直接调用构造函数的行为是什么?

答:

直接调用构造函数将产生一个临时对象

临时对象的生命周期只有一条语句的时间

临时对象的作用域只在一条语句中

临时对象是C++中值得警惕的灰色地带

#include <stdio.h>

class Test {
int mi;
public:
Test(int i)
{
mi = i;
}
Test()
{
Test(0);
// 调用Test(int i),得到了一个临时对象,生命周期只有这句话,过了之后临时对象就被析构,临时对象没有名字,作用域也只有这句话,过了之后,不能再被访问。这里的临时对象几乎就没有作用。这个0根本就没有设置到mi上
}
// 等价于
Test(){ };
void print() {
printf("mi = %d\n", mi);
}
}; int main()
{
Test t; t.print(); return 0;
} // 解决办法
// 提供一个私有的init函数,做初始设置
class Test {
int mi;
void init(int i)
{
mi = i;
}
public:
Test(int i) {
printf("Test(int i)\n");
init(i);
} Test(){
printf("Test()\n");
init(0); // 调用的普通私有函数,不会产生临时对象
}; void print() {
printf("mi = %d\n", mi);
} ~Test()
{
printf("~Test()\n");
}
}; int main()
{
printf("main begin\n"); Test(); // 直接调用构造函数,会产生一个临时对象
Test(10); // 产生临时对象 printf("main end\n") return 0;
} /*结果
main begin
Test()
~Test()
Test(int i)
~Test()
*/ int main()
{
printf("main begin\n");
Test().print(); // Test()结果是一个临时对象,是一个合法的对象,然后操作它的成员函数
Test(10); // 产生临时对象
printf("main end\n") return 0;
} /*结果
main begin
Test()
mi = 0 // 临时对象的打印
~Test()
Test(int i)
mi = 10 // 临时对象的打印
~Test()
*/

编译器的行为:现代C++编译器在不影响最终执行结果的前提下,会尽力减少临时对象的产生!!!

#include <stdio.h>

class Test
{
int mi;
public:
Test(int i)
{
printf("Test(int i) : %d\n", i);
mi = i;
}
Test(const Test& t)
{
printf("Test(const Test& t) : %d\n", t.mi);
mi = t.mi;
}
Test()
{
printf("Test()\n");
mi = 0;
}
int print()
{
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
}; Test func()
{
return Test(20); // 应该是返回一个临时对象
} int main()
{
Test t(10);
Test t = Test(10); // 1、生成一个临时对象;2、用临时对象初始化t
// ==> 调用拷贝构造函数
// 但是结果并没有打印拷贝构造函数,说明编译器没有生成临时变量
// 原因是现代编译器都会尽量减少临时变量的产生,
// 编译器将这句话等价成了 Test t(10)
// 临时变量的产生会带来性能上的问题
t.print(); Test tt = func();
tt.print(); // 会打印出20
/*
理论上应该是要调用拷贝构造函数,但是没有
编译器将这句话等价成了 ==> Test tt = Test(20) ==> Test tt = 20;
*/ return 0;
}

小结

直接调用构造函数将产生一个临时对象

临时对象是性能的瓶颈,也是BUG的来源之一

现代C++编译器会尽力避开临时对象

实际工程开发中需要认为地避开临时对象

二十一、C++中的临时对象的更多相关文章

  1. C++中的临时对象

    1,临时对象神秘在于不知不觉就请入程序当中,并且给程序带来了一定的问题: 2,下面的程序输出什么?为什么? #include <stdio.h> class Test { int mi; ...

  2. 认识C++中的临时对象temporary object 分类: C/C++ 2015-05-11 23:20 137人阅读 评论(0) 收藏

    C++中临时对象又称无名对象.临时对象主要出现在如下场景. 1.建立一个没有命名的非堆(non-heap)对象,也就是无名对象时,会产生临时对象. Integer inte= Integer(5); ...

  3. (二十一)WebGIS中鹰眼的实现思路

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 鹰眼功能是WebGIS中的一种常见功能,利用一些开源的框架实现 ...

  4. AngularJS进阶(二十一)Angularjs中scope与rootscope区别及联系

    Angularjs中scope与rootscope区别及联系 scope是html和单个controller之间的桥梁,数据绑定就靠他了.rootscope是各个controller中scope的桥梁 ...

  5. 二十一、JavaScript之访问对象属性

    一.代码如下 二.执行效果如下 <!DOCTYPE html> <html> <meta http-equiv="Content-Type" cont ...

  6. 读书笔记_Effective_C++_条款二十一:当必须返回对象时,别妄想返回其reference

    在栈空间的临时成员变量在函数生命期结束后无法传出 friend A& operator*(const A& a, const A& b) { A temp; temp.data ...

  7. 从汇编看c++中临时对象的析构时机

    http://www.cnblogs.com/chaoguo1234/archive/2013/05/12/3074425.html c++中,临时对象一旦不需要,就会调用析构函数,释放其占有的资源: ...

  8. 【编程篇】C++11系列之——临时对象分析

    /*C++中返回一个对象时的实现及传说中的右值——临时对象*/ 如下代码: /**********************************************/ class CStuden ...

  9. 与临时对象的斗争(上)ZZ

    C++ 是一门以效率见长的语言(虽然近来越来越多的人“不齿”谈及效率,我深以为不然,在某一次的程序编写中不对效率锱铢必较并不意味意味着我们就不应该追求更多的更好的做法).总之吧,相比起其它语言,程序员 ...

随机推荐

  1. 剑指Offer的学习笔记(C#篇)-- 求1+2+3+...+n

    题目描述 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). 一 . 直接解题吧 芽儿呦,突然觉得,我不说! ...

  2. wcf双工通信

    一直以为感觉双工没弄懂,着实觉得很惆怅,在网上了解下双工的一些特点,直接上代码,以便以后项目中用的着: service层: 定义一个IDuplexHello服务接口 [ServiceContract( ...

  3. spring boot 参数转换

    参数调用方式: 1. localhost:8080/person/properties/to/json body参数设置: 2. localhost:8080/person/json/to/prope ...

  4. C# Dictionary类型转json方法之一

    using Newtonsoft.Json;//引用命名空间 Dictionary<string, string> Content = new Dictionary<string, ...

  5. Linux —— shell认识与基础命令

    shell 基础 shell路径: /etc/shells 系统shell版本: $SHELL 在父shell中可以调用子shell echo 把指定内容输出到屏幕上 操作选项: -e: 支持反斜杠控 ...

  6. Codeforces 1167E(思路、数据处理)

    思路 不难想到枚举\(l\),那如何高效求出最小的\(r\)?这样答案加上\(x-r+1\)即可. 如果\(l\)并没在序列里出现--没啥想法:如果\(l\)是序列里的数,我们可以做的事情是记下每个数 ...

  7. Linux中/etc/passwd 和 /etc/shadows 详解

    linux操作系统上的用户如果需要登录主机,当其输入用户名和密码之后: 首先在/etc/passwd文件中查找是否有你的账号,如果没有无法登录,如果有的话将该用户的UID和GID读出来,此外将此用户的 ...

  8. 【持续更新】Spring相关

    什么是IoC 什么是AoP Bean的实例化方法--3种 Bean的作用域--常用2种 Bean的生命周期 Bean的装配方式 基于xml的2种装配方式 基于Annotaton的装配方式

  9. 安装vs2013提示必须安装ie10的解决办法

    虽说应该直接安装ie10,但试了下并不是很顺利,找到如下解决办法,亲测通过. 新建bat文件,内容如下,右键以管理员身份运行,vs即可正常安装. @ECHO OFF :IE10HACK REG ADD ...

  10. vim的命令

    下面是从一个博客里摘抄出来的, 供自己学习使用.   在命令状态下对当前行用== (连按=两次), 或对多行用n==(n是自然数)表示自动缩进从当前行起的下面n行.你可以试试把代码缩进任意打乱再用n= ...