显式调用构造函数产生的悲剧
昨天一个同学让我帮他调试程序,发现一个诡异的问题,明明一个类的私有成员被赋值了,但运行时却总是不定的值。仔细检查了好久,才发现原来他把构造函数当作普通函数进行了显式调用,结果产生了悲剧。
将他的问题简单的抽象如下:
大家看看下面这段代码的输出结果是什么?这段代码有问题么?
#include <iostream> class CTest {public:CTest() { m_a = 1; } CTest(int b) { m_b = b; CTest(); } ~CTest() {} void show { std::cout << m_a << std::endl; std::cout << m_b << std::endl; } private: int m_a; int m_b; }; void main() { CTest myTest(2); myTest.show(); }
-----------------------------------------------------------
【分析】
-----------------------------------------------------------
输出结果中,m_a是一个不确定的值,因为没有被赋初值,m_b 为2
注意下面这段代码
CTest(int b)
{m_b = b;CTest();
}
在调用CTest()函数时,实际上是创建了一个匿名的临时CTest类对象,CTest()中赋值 m_a = 1 也是对该匿名对象赋值,故我们定义的myTest的m_a其实没有被赋值。说白了,其实构造函数并不像普通函数那样进行一段处理,而是创建了一个对象,并且对该对象赋初值,所以显式调用构造函数无法实现给私有成员赋值的目的。
这个例子告诉我们以后代码中千万不要出现使用一个构造函数显式调用另外一个构造函数,这样会出现不确定性。其实一些初始化的代码可以写在一个单独的init函数中,然后每一个构造函数都调用一下该初始化函数就行了。
在此,顺便再提出另外一个问题以供思考:
CTest *p = NULL; void func() { p = new CTest(); }
代码右边显示调用CTest(),是否依然会产生一个匿名的临时对象a,然后将该匿名的临时对象a的地址赋给指针p? 如果是这样的话,出了func函数后,临时对象a是否会被析构? 那指针p不成为了野指针了?你能解释这个问题么?
关于c++构造函数的详细分类与示例在《C++构造函数详解》一文中有详细的描述,有兴趣的读者可以看看:http://ticktick.blog.51cto.com/823160/194307
显式调用构造函数产生的悲剧相关推荐
- C++中派生类隐式调用与显式调用基类的构造函数
通过派生类的构造函数调用基类的构造函数有两种方式,隐式和显式两种. 所谓隐式方式就是在派生类的构造函数中不指定对应的基类的构造函数,这个时候调用的是基类的默认构造函数(即含有默认参数值或不带参数的构造 ...
- java构造函数未定义_错误:隐式超级构造函数Person()未定义.必须显式调用另一个构造函数....
今天写程序的时候发现了一个错误: public class Test { public static void main(String[] args) { Student s1 = new Stude ...
- linux下动态链接库(.so)的显式调用和隐式调用
进入主题前,先看看两点预备知识. 一.显式调用和隐式调用的区别 我们知道,动态库相比静态库的区别是:静态库是编译时就加载到可执行文件中的,而动态库是在程序运行时完成加载的,所以使用动态库的程序的体积要 ...
- C++构造函数与析构函数
几乎所有的面向对象的编程语言都保护构造函数与析构函数,好学者就要举手了,啥情况啊,Java里面不就没有析构函数嘛.好吧,你问倒我了,不过可以认为Java的垃圾自动回收机制实现了对象析构的功能.管他呢, ...
- Java构造函数可以私有,我们可以在Java中使用私有的构造函数吗?
甲构造用于创建时初始化对象.从语法上讲,它类似于一种方法.区别在于,构造函数的名称与其类相同,并且没有返回类型. 无需显式调用构造函数,这些构造函数会在实例化时自动调用. 构造函数允许的访问说明符/修 ...
- C++基础学习9:构造函数和析构函数
1. 构造函数用来对类对象进行初始化,它完成对内存空间的申请.赋初值等工作. 2. 析构函数主要是用来做清理工作的. 补充: 函数名或变量名前面有"::"但是没有类名,说明 ...
- C++11中的右值引用(对比左值引用和常引用)、移动构造函数和引用标识符
Hello!各位同学们大家好!逗比老师最近说起来还是挺尴尬的,为什么这么说呢?因为以前我对自己的C++水平还是相当自信的,经常以"精通"来自我评价.但是最近发现自己好像对C++11 ...
- 【原创】Performanced C++ 经验规则 第一条:你不知道的构造函数(上)
Performanced C++ 经验规则 前言:Performanced C++,意为"高性能C++"编程,是笔者和所在团队多年C++编程总结的经验规则,按条款方式讲述(参考了& ...
- C++构造函数详解及显示调用构造函数
c++类的构造函数详解 一. 构造函数是干什么的 class Counter { public: // 类Counter的构造函数 // 特点:以类名作为函数名,无 ...
最新文章
- 跟我学XSL(二) -XSL的运算符
- SPCS 2021 开启征稿 | 第二届信号处理与计算机科学国际学术会议
- boost::hana::find用法的测试程序
- linux-VM无法连接mks套接字连接尝试次数太多
- mariadb mysql 5.6_MySQL 5.6 和 MariaDB-10.0 的性能比较测试
- 信息学奥赛一本通 1013:温度表达转化 | OpenJudge NOI 1.3 08
- django 视图-----视图函数
- python正则表达式使用修饰符
- 自动化测试的理想境界:AppCrawler自动遍历工具
- 7z替换exe文件内容不能替换文件_Windows小技巧 批处理文件实现目录下文件批量打包压缩...
- java单例模式的7种实现方式
- php默认登录文件,PHP 网站修改默认访问文件的nginx配置
- java执行update的方法_解决Hibernate4执行save()或update()无效问题的方法
- 计算机运算法则图鉴,AP微积分BC TI-Nspire计算器使用指南 正确使用计算器5分到手轻而易举...
- 用java遍历所有文件夹,将word文件转换为txt格式
- 网易云Android高级,网易云音乐Android新版 一键升本地音质
- 电脑键盘打字跳转计算机,电脑键盘打字方法
- 自学Java第二天 解决java不能输出中文问题
- 服务器系统启用来宾用户,系统日志中出现Internet来宾账户
- 前端架构,前端架构组织结构,目录结构架构