2703|1

2146

帖子

8

TA的资源

五彩晶圆(初级)

楼主
 

一个C++有关构造函数的问题,没想明白 [复制链接]

本帖最后由 wsmysyn 于 2018-10-26 21:07 编辑

如题,C++高级特性不怎么经常用,一直当C来用,偶尔调用别人的C++ 类的API,
今天遇到一个没想明白的问题,如图。

我写了三个类CA、CB、CC
构造函数部分,
CA采用无参构造
CB采用了一个void类型的指针参数,默认为NULL
CC采用一个int类型的指针参数,默认为NULL

然后在Test函数中进行实例化
使用new和不使用new的区别是,new在堆上创建对象,没有new是在栈上创建对象
new创建的对象,可以全局访问,不需要时,需要用delete;栈上的对象,在离开作用域之后,自动销毁

使用new的时候,需要一个类的指针,来指向这个对象

我分别用三种语法来写,
Cx cx;   --> 1

Cx cx = new Cx();  --> 2

Cx* cx = new Cx(); --> 3


发现只有CB的类是可以支持这三种写法,其他都是不支持2的写法,提示没有相应的构造函数,是Cx*转换为Cx
这个我理解,new的实现是返回一个void类型的指针,和左值类型不符

我的问题:
1、为什么构造函数传入void类型指针之后就可以支持2这种操作呢?
2、从运行的结果上看,2这种实例化方式,调用了两次CB的构造函数,这是为什么呢?
3、在函数结尾,delete三个指针,销毁了这三个对象,分别调用了三个类的析构函数,以及函数结束后,栈上的对象也被销毁,同样分别调用了三个类的析构函数。但是为什么少了1次CB的析构函数呢?构造的时候调用了4次,为什么析构的时候,只有3次呢?

浏览了一下C++ 11的标准,但是并没有找到地方
网上暂时也没搜到这类的描述,(可能提问的姿势不对...)


代码:


运行结果:



  1. class CA
  2. {
  3. public:
  4.     CA() { std::cout << "Class A" << std::endl; };
  5.     ~CA() { std::cout << "Class A die..." << std::endl; };
  6. };
  7. class CB
  8. {
  9. public:
  10.     CB(void* pVOID = NULL) { std::cout << "Class B" << std::endl; };
  11.     ~CB() { std::cout << "Class B die..." << std::endl; };
  12. };
  13. class CC
  14. {
  15. public:
  16.     CC(int* pLength = NULL) { std::cout << "Class C" << std::endl; }
  17.     ~CC() { std::cout << "Class C die..." << std::endl; };
  18. };

  19. void Test(void)
  20. {
  21.     CA  a0;
  22.     //CA  a1 = new CA();
  23.     CA* a2 = new CA();

  24.     CB  b0;
  25.     CB  b1 = new CB();
  26.     CB* b2 = new CB();

  27.     CC  c0;
  28.     //CC  c1 = new CC();
  29.     CC* c2 = new CC();

  30.     delete a2;
  31.     delete b2;
  32.     delete c2;
  33. }

  34. int main(int argc, char* argv[])
  35. {   
  36.     Test();
  37.     system("pause");

  38.     return 0;
  39. }
复制代码




此帖出自模拟电子论坛
点赞 关注
个人签名坐而言不如起而行

回复
举报

2146

帖子

8

TA的资源

五彩晶圆(初级)

沙发
 
后来搞明白了。。
实际上是C++的一种隐式转换

CB b1 = new CB();

等同于 -->
CB* temp = new CB();
CB b1(temp);

因为CB的构造函数传入类型是void*,new 返回的也是void*类型,所以默认尝试做了一个隐式转换,将临时对象,作为构造函数的参数,传递进去了。并在栈上做了创建了一个对象,所以可以通过编译(可能并不是你想要的这种结果,但却是发生了)

所以,构造函数是4次,多了一次隐式的对象构造;在析构的时候,临时对象并没有被析构掉,造成了内存泄露

尤其是单参构造函数出现隐式转换的几率比较大,可能会有意想不到的bug。避免这种隐式的转换是在构造函数前加上explicit 禁止隐式转换。

此帖出自模拟电子论坛
 
个人签名坐而言不如起而行
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表