今天下午在研究虚函数的时候遇到了一个问题,觉得很有意思,记录一下。

先看代码:

 class Base
{
public:
Base(int value)
{
m_nValue = value;
cout << "object(" << this << "){" << this->m_nValue << "} is constructing!" << endl;
} ~Base()
{
cout << "object(" << this << "){" << this->m_nValue << "} is destroy!" << endl;
}
private:
int m_nValue;
}; int main()
{
Base b();
(Base)b;
return ;
}

打印结果:

为什么会调用两个析构函数?一个析构函数是可以理解的,为什么要调用两次?

其实这里是调用了一次拷贝构造函数。调整一下代码

 class Base
{
public:
Base(int value)
{
m_nValue = value;
cout << "object(" << this << "){" << this->m_nValue << "} is constructing!" << endl;
}
//新增部分
Base(const Base& b)
{
this->m_nValue = b.m_nValue;
cout << "object(" << this << "){" << this->m_nValue << "} is copy constructing!" << endl;
}
//新增部分结束!
~Base()
{
cout << "object(" << this << "){" << this->m_nValue << "} is destroy!" << endl;
}
private:
int m_nValue;
}; int main()
{
Base b();
(Base)b;
return ;
}

执行结果:

注意红框里边标注的!(Base)b隐式的调用了拷贝构造函数和析构函数。

(Base)b的操作这样看起来不是很舒服,我们把再修改一下代码

 void fun(Base b)
{
//do nothing
}
int main()
{
Base b();
fun(b);
return ;
}

执行结果:

b在进入fun这个函数的时候,发生了拷贝构造到析构的操作。这样就很容易理解刚开始的问题:为什么会出现两次析构函数。

再修改一下代码,验证一下:

 void fun(Base& b)
{
//do nothing
cout << "fun" << endl;
}
int main()
{
Base b();
fun(b);
return ;
}

执行结果。

这也就是为什么要用引用 Base& b 而直接使用 Base b 的原因了。当然,最好还是加上const。

上述就是这个问题的记录

C++对象的构造、析构与拷贝构造的更多相关文章

  1. C++基本函数的调用优化(构造、拷贝构造、赋值)

    合理的函数可提升时间和空间的利用率 //Test1.h #include<iostream> using namespace std; struct ST { private: int a ...

  2. C++之旅:拷贝构造与友元

    拷贝构造与友元 拷贝构造是在构造一个对象的时候将已有对象的属性拷贝给新的对象:友元可以让一个类的所有属性(主要是private)对特定的类开放 拷贝构造 如果没有复写拷贝构造函数,系统会帮我们默认生成 ...

  3. C++ //拷贝构造函数调用时机//1.使用一个已经创建完毕的对象来初始化一个新对象 //2.值传递的方式给函数参数传值 //3.值方式返回局部对象

    1 //拷贝构造函数调用时机 2 3 4 #include <iostream> 5 using namespace std; 6 7 //1.使用一个已经创建完毕的对象来初始化一个新对象 ...

  4. 构造 & 析构 & 匿名对象‍

    ‍以前仅知道创建对象,但对匿名对象的了解基本为0. 通过阅读google chromium源代码 中关于 log 的使用,查阅相关资料,了解了一下匿名对象,予以记录. 什么是匿名对象‍ 匿名对象可以理 ...

  5. STL——容器(Set & multiset)的默认构造 & 带参构造 & 对象的拷贝构造与赋值

    1. 默认构造 set<int> setInt;              //一个存放int的set容器. set<float> setFloat;          //一 ...

  6. C++ 构造函数、析构函数、拷贝构造、赋值运算符

    之所以要把它们放在一起,是因为在使用C/C++类语言的时候,很容易混淆这几个概念(对Java来说完全没有这样的问题,表示Javaor完全没有压力). 先建立一个测试类(包含.h和.cpp) //~ P ...

  7. Effective C++笔记:构造/析构/赋值运算

    条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函 ...

  8. Effective C++ 2.构造 析构 赋值运算

    //条款07:为多态基类声明virtual析构函数 // 1.若基类的析构函数不定义为虚函数,由于基类的指针或引用可以指向派生类的对象,则在删除基类对象的时候可能会出错,导致破坏数据结构. // 2. ...

  9. C++类构造析构调用顺序训练(复习专用)

    //对象做函数参数 //1 研究拷贝构造 //2 研究构造函数,析构函数的调用顺序 //总结 构造和析构的调用顺序 #include "iostream" using namesp ...

随机推荐

  1. Pandas 基础(4) - 读/写 Excel 和 CSV 文件

    这一节将分别介绍读/写 Excel 和 CSV 文件的各种方式: - 读入 CSV 文件 首先是准备一个 csv 文件, 这里我用的是 stock_data.csv, 文件我已上传, 大家可以直接下载 ...

  2. windows常见软件库

    1.护卫神软件库 http://soft.huweishen.com/special/1.html 2.护卫神windows资料库 http://v.huweishen.com/ 3.国超软件下载 h ...

  3. webpack简单修改版本号(单页面)

    写了一个js文件,可以尽量最简单的修改版本号 package.json配置: updateV.js放置位置: updateV.js: var fs = require('fs'); //文件读写 va ...

  4. 实现android"转盘抽奖"小项目后感想

    我这次做的小项目是android的转盘抽奖,因为这个小项目中有进程的调度,加锁等细节,而我们组的竞赛系统中也有这样的问题.通过这次的实践我发现了自己的好多问题也学到了很多. 个人问题: 1.自己的动手 ...

  5. Android测试(三)——APK文件反编译

    APK文件反编译: 在进行反编译操作前,先简单介绍下smali文件: smali是一种文件格式,语法和Jasmine的语言类似,这些smali文件包含开发应用程序时编写的java类的代码. 工具:ja ...

  6. ZCRM_AU_MAIL

    FUNCTION ZCRM_AU_MAIL. *"---------------------------------------------------------------------- ...

  7. 主机连接虚拟机的mysql 记录

    检查远程的虚拟机是否可以ping通过 查看虚拟机IP为192.168.38.128 cmd窗口ping 192.168.38.128,出现如下界面说明是可以的 检查虚拟机mysql的端口号是否对外开通 ...

  8. jquery 获取表单的内容以JSON对象形式返回

    添加一个serializeJson方法 <!DOCTYPE html> <html> <head> <meta charset="UTF-8&quo ...

  9. Android开发 ---SQLite数据库,lock文件,结果集游标,适配器,安全退出,给连接设置下划线,编辑器,投影,ContentValues存储,DbHelper,activity栈

    目录截图: 1.activity_main.xml 主界面效果: <?xml version="1.0" encoding="utf-8"?> &l ...

  10. Python编程高级特性--迭代器

    一.简单介绍 直接作用于for循环的数据类型有以下几种: 集合数据类型: list 例如:list = ["yuhaohao", "lisheng", &quo ...