C++对象的构造、析构与拷贝构造
今天下午在研究虚函数的时候遇到了一个问题,觉得很有意思,记录一下。
先看代码:
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++对象的构造、析构与拷贝构造的更多相关文章
- C++基本函数的调用优化(构造、拷贝构造、赋值)
合理的函数可提升时间和空间的利用率 //Test1.h #include<iostream> using namespace std; struct ST { private: int a ...
- C++之旅:拷贝构造与友元
拷贝构造与友元 拷贝构造是在构造一个对象的时候将已有对象的属性拷贝给新的对象:友元可以让一个类的所有属性(主要是private)对特定的类开放 拷贝构造 如果没有复写拷贝构造函数,系统会帮我们默认生成 ...
- C++ //拷贝构造函数调用时机//1.使用一个已经创建完毕的对象来初始化一个新对象 //2.值传递的方式给函数参数传值 //3.值方式返回局部对象
1 //拷贝构造函数调用时机 2 3 4 #include <iostream> 5 using namespace std; 6 7 //1.使用一个已经创建完毕的对象来初始化一个新对象 ...
- 构造 & 析构 & 匿名对象
以前仅知道创建对象,但对匿名对象的了解基本为0. 通过阅读google chromium源代码 中关于 log 的使用,查阅相关资料,了解了一下匿名对象,予以记录. 什么是匿名对象 匿名对象可以理 ...
- STL——容器(Set & multiset)的默认构造 & 带参构造 & 对象的拷贝构造与赋值
1. 默认构造 set<int> setInt; //一个存放int的set容器. set<float> setFloat; //一 ...
- C++ 构造函数、析构函数、拷贝构造、赋值运算符
之所以要把它们放在一起,是因为在使用C/C++类语言的时候,很容易混淆这几个概念(对Java来说完全没有这样的问题,表示Javaor完全没有压力). 先建立一个测试类(包含.h和.cpp) //~ P ...
- Effective C++笔记:构造/析构/赋值运算
条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函 ...
- Effective C++ 2.构造 析构 赋值运算
//条款07:为多态基类声明virtual析构函数 // 1.若基类的析构函数不定义为虚函数,由于基类的指针或引用可以指向派生类的对象,则在删除基类对象的时候可能会出错,导致破坏数据结构. // 2. ...
- C++类构造析构调用顺序训练(复习专用)
//对象做函数参数 //1 研究拷贝构造 //2 研究构造函数,析构函数的调用顺序 //总结 构造和析构的调用顺序 #include "iostream" using namesp ...
随机推荐
- SELinux 的初始和基本操作
SELinux 主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则). 设想一下,如果一个以 root 身份运行的网络服务存在 0day 漏洞,黑客就可以利用这个漏洞,以 root 的 ...
- shiro框架
Shiro Shiro简介 SpringMVC整合Shiro,Shiro是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理等功能. Authentication:身份认证/登录,验证用 ...
- (转)决定系数R2
有些讲得太烂了,我来通俗的梳理一下R2. Calculating R-squared 在线性回归的模型下,我们可以计算SE(line), SE(y均值). The statistic R2descri ...
- 通过class改变样式
1.判断class属性 判断一个元素中是否含有指定的class属性值 function hasClass(obj,cn){ //创建正则表达式 var reg=new RegExp("\\b ...
- hdu5421Victor and String 两端加点的pam
题意:要求维护两端加点的字符串,以及查询本质回文串个数和所有回文串个数 题解:pam,两端加点过程详见ioi2017国家集训队论文,维护一个最长回文前缀和最长回文后缀即可,fail不用两个,能前后共用 ...
- 数据结构与算法之PHP排序算法(冒泡排序)
一.基本思想 冒泡排序算法是重复地走访过要排序的数列,一次比较相邻的两个元素,如果他们的顺序与排序要求相反,就将它们互换,直到没有再需要交换的数字,则说明排序完成. 二.算法过程 1)比较相邻的两 ...
- 单机器搭建 zk 集群
在一台机器上配置 2 节点的 zk 集群,zk1 和 zk2 的 serverid 分别为 1 和 2,本机 ip 是 192.168.40.1 zk1 相关配置: dataDir=E:/test/z ...
- TCP/IP协议网络编程以及UDP和TCP之传输协议
1.什么是TCP/IP协议? 网络编程协议有很多,目前应用最广泛的是TCP/IP协议(Transmission Control Protocal/Internet Protoal 传输控制协议/英特网 ...
- Android 音视频深入 十 FFmpeg给视频加特效(附源码下载)
项目地址,求starhttps://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg(AVfilte ...
- navicat连接Oracle数据库
记录一下navicat连接Oracle数据库过程: 一.根据自己版本去Oracle官网下载instantclient 地址:https://www.oracle.com/technetwork/top ...