显式调用构造函数产生的悲剧

简介:

昨天一个同学让我帮他调试程序,发现一个诡异的问题,明明一个类的私有成员被赋值了,但运行时却总是不定的值。仔细检查了好久,才发现原来他把构造函数当作普通函数进行了显式调用,结果产生了悲剧。

    

将他的问题简单的抽象如下:

    

大家看看下面这段代码的输出结果是什么?这段代码有问题么?


#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


注意下面这段代码


1
2
3
4
5
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不成为了野指针了?你能解释这个问题么?



本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/294573,如需转载请自行联系原作者

相关文章
DataFrame(12):数据转换——apply(),applymap()函数的使用(一)
DataFrame(12):数据转换——apply(),applymap()函数的使用(一)
DataFrame(12):数据转换——apply(),applymap()函数的使用(一)
|
JavaScript API
vue的select下拉框多选项-multiple属性
vue的select下拉框多选项-multiple属性
734 0
|
编解码 人工智能 数据格式
PIE-ENGINE:Modis-Aqua产品包含了L3 Mapped数据集
PIE-ENGINE:Modis-Aqua产品包含了L3 Mapped数据集
505 0
|
JavaScript 前端开发 算法
彻底理解JavaScript中的类型转换(下)
彻底理解JavaScript中的类型转换(下)
174 0
|
负载均衡 中间件 应用服务中间件
Nginx动静分离详解以及配置
1.Nginx动静分离概念 动静分离,通过中间件将动态请求和静态请求进行分离,分离资源,减少不必要的请求消耗,减少请求延时。 好处:动静分离后,即使动态服务不可用,但静态资源不会受到影响 通过中间件可以将动态请求和静态请求进行分离
552 0
Nginx动静分离详解以及配置
|
小程序 Java 关系型数据库
大厂程序员接私活被坑, 还被放鸽子,那源码就开源-基于SSM仿知乎小程序
一,系统演示;二,系统的简介;三,核心代码展示
213 0
大厂程序员接私活被坑, 还被放鸽子,那源码就开源-基于SSM仿知乎小程序
|
NoSQL JavaScript 前端开发
nodejs操作redis
nodejs操作redis
348 0
|
存储 Kubernetes 前端开发
一款不错的 Go Server/API boilerplate,使用 K8S+DDD+CQRS+ES+gRPC 最佳实践构建
一款不错的 Go Server/API boilerplate,使用 K8S+DDD+CQRS+ES+gRPC 最佳实践构建
847 0
一款不错的 Go Server/API boilerplate,使用 K8S+DDD+CQRS+ES+gRPC 最佳实践构建
|
Web App开发 XML 供应链
前端周卡第十一期
前端周刊发表每周前端技术相关的大事件、文章教程、一些框架的版本更新、以及代码和工具。每周定期发表,欢迎大家关注、转载。
前端周卡第十一期
|
存储 算法 安全
Java中的锁原理、锁优化、CAS、AQS详解!
一、为什么要用锁? 锁-是为了解决并发操作引起的脏读、数据不一致的问题。
192 0
Java中的锁原理、锁优化、CAS、AQS详解!