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

先看代码:

 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. HADOOP HA 踩坑 - 所有 namenode 都是standby

    报错: 无明显报错 状况: 所有namenode都是standby,即ZK服务未生效 尝试一:手动强制转化某个namenode为active 操作:在某台namenode上,执行 hdfs haadm ...

  2. echarts tooltip巧用

    tooltip : { trigger: 'item', triggerOn: 'click', formatter:function(params,ticket,callback){ var res ...

  3. 关于ExpressionChangedAfterItHasBeenCheckedError

    最近在stackoverflow上似乎每天都有一些关于angular报错‘ExpressionChangedAfterItHasBeenCheckedError’的问题.发生这些问题通常是由于angu ...

  4. Ajax+Struts2用户注册功能实现

    详细请参考源码(Github):https://github.com/QQ3330447288/ajaxRegister 1.目录结构 2.截图 3.核心代码: register.jsp <sc ...

  5. maven 项目编译失败

    tomcat 加载项目启动后 提示  找不到web-context配置 或者某一个类加载错误 发生在 从根目录新导入新的 未打开项目之后 install 失败  java 文件未编译成 class 解 ...

  6. Docker Image管理学习笔记,ZT

    Docker Image管理学习笔记 http://blog.csdn.net/junjun16818/article/details/38423391

  7. HTTP协议(二)之确保web安全的HTTPS

    一.概述 https并非是应用层的一种新协议.只是HTTP通信接口部分用SSL和TLS协议替代. 通常,HTTP直接和TCP通信.当使用SSL时,则演变成先和SSL通信,再由SSL和TCP通信了. 简 ...

  8. 整理整理Linux命令

    自用.. 1. 查看当前文件目录下,所有文件消耗的磁盘容量 du -h ./ 2. 系统中文件的使用情况 df -h 和du -h显示磁盘大小不一致可能是因为使用rm删除时,文件存在link,没有删除 ...

  9. Sonya and Problem Wihtout a Legend CodeForces - 714E (dp)

    大意: 给定序列, 每次操作可以任选一个数+1/-1, 求最少操作数使序列严格递增. 序列全-i后转化为求最少操作数使序列非降, 那么贪心可以知道最后$a_i$一定是修改为某一个$a_j$了, 暴力d ...

  10. Java多线程——Condition条件

    简介 Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signa ...