加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

C/C++ new 创建对象加不加括号的区别

(2015-09-30 01:44:04)
标签:

c/c

new

分类: C/CPP
比如,
ClassX a=new ClassX;
ClassX b=new ClassX();
有区别?

一、看到很多种说法:  http://bbs.csdn.net/topics/320161716

1.“加括号调用没有参数的构造函数,不加括号调用默认构造函数或唯一的构造函数,看需求”
明显不对,假设人为定义一个class,并只定义了一个带参数的构造函数(注意:一旦自定义了任何构造函数,默认构造函数(Default Empty Constructor)将不复存在 ),那这个函数就是唯一的构造函数,那new class()的时候就调用它了?
 
可是new xx()的方式,参数值都没法传递。。。显然,不可能调用带参数的构造函数。
 
实际上,这种情况下, new xx()根本通过不了编译,因为这种方式是调用无参构造函数来初始化一个类实例的,而这个类根本没有无参构造函数
 
然而,很多朋友都认为是这样的 (⊙﹏⊙)b……

2.“对于自定义类型(class/struct),调用的都是默认构造函数,没区别的。
只不过对于内建类型(int, doube, char)不太一样,加了扩号会做默认值初值化,比如:
int* new int;//p指向的int值是不确定的;
int* new int();//q指向的int值为0。”
当初比较赞这个观点,但是后来测了一下发现,也不完全是这样的!

-----------------------------------------------------------------------------------------------------
二、实践出真知:


        int* p = new int;//printf结果         *p的值为不确定的整形;
        int* q = new int();//                 *q的值是0!

        double* p = new double;//           *p的值不确定的浮点类型;
        double* q = new double();//        *q的值是0!

        int* a1 = new int[10];       //     遍历结果:        元素值是不确定的;
        int* a2 = new int[10]();     //  遍历结果:        0,0,0,……0 

//可见,加了括号,new确实可以在创建对象的同时把它初始化为0 
(以前new int[N]以后,还傻傻的 memset来初始化,看来不用了!)

那么对于Class呢? 
class XX{
public:
   int a;
   XX(){       //显式声明一个无参构造函数(EmptyConstructor)
          cout<<"called Empty Constructor  "<<endl; 
      }       
};
           XX *p1=new XX;           //输出"called Empty Constructor "         cout<<p1->a:  不确定 
           XX *p2=new XX();         //输出"called Empty Constructor "         cout<<p2->a:  也是不确定值!
//可见,加不加括号,都是调用了无参构造函数,但成员值都没有被初始化为0,
//似乎似乎观点2是正确的,即对于class,用new创建的时候,加不加括号都是一样的, 都没有初始化的作用, 是这样吗?

去掉无参构造函数 的显式声明, 再次测试,这时候将会调用默认构造函数:
class XX{
public:int a;
};
              XX *p1=new XX; //cout<<p1->a    //    不确定的值
              XX *p2=new XX(); //cout<<p2->a //    0   !!! (看来也能初始化为0,观点2说的也不完全正确)
//看来 采用"new classXX()"的方式创建class的对象,也具有初始化成员为0的作用 !

三、分析
我们知道,在没有显式定义构造函数的时候,系统默认会设定default Empty Construct,即默认无参构造函数而一旦显式声明了任何其他构造函数,这个defaule Empty Construct 就不存在了。尤其是当我们定义了一个带参的构造函数以后,必须再显式定义一个无参构造函数,否则 XX xx;  或者 XX *p=new XX 或者 XX p=new XX()都无法通过编译!说明这三种方式都是在调用无参构造函数
 
上面两次尝试的差异在于:
第一次new xx(),是调用的用户自定义的无参构造函数;
第二次new xx(),是调用的系统的无参构造函数,也就是那个  default Empty Construct
 
所以,从结果可以看出,实现初始化为0是依靠的系统的默认无参构造函数(  default Empty Construct)!
前一个例子正是由于我们自定义了Empty构造函数,覆盖了系统的default Empty Construct,同时自己定义的empty构造函数又没有实现初始化为0的操作,所以成员没有被初始化为0。

 
至于观点2,“对于内建类型(int, doube, char)不太一样,加了扩号会做默认值初值化”
由于系统类型的“默认无参构造函数”不可能被用户改写,所以type xx=new  type()都是调用的default empty constructor,所以一定具有初始化为0的效果!(观点正确)
 
对于自定义类型(class/struct),调用的都是默认构造函数,没区别的。":
但是对于Class,classX *p=new classX() 和 classX *p =new class效果确实都是一样的,但如果用户显示定义了构造函数,调用的就都是用户定义的那个Empty Constructor,而不是默认构造函数。(观点错误)

 
四、总结:
type *p=new type 不同于
type *p=new type()
前者只具有创建对象(变量)的作用,后者还具有初始化对象(变量)为0的作用!

*顺便提一句: classXX p; 和 classXX p();不一样,
前者是调用empty constructor来创建对象,并且不具备初始化为0的作用,
而后者则是声明了一个名字为p、返回类型为classXX的函数!

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有