new 对象加括号和不加括号的区别

还有pod 

PLAIN OLD DATA

  plain old data 的缩写(POD)一个普通的古老的数据结构(POD)是一种数据结构。它仅作为被动的收藏的字段值,不使用封包或者otherobject-oriented特征。(plain old data structure(POD) is a data structurethat is represented only as passive collections of field values, without using encapsulationor otherobject-orientedfeatures.)

  在C++中,我们把传统的C风格的struct叫做POD(Plain Old Data)对象。一般来说,POD对象应该满足如下特性。

  对于POD类型T的对象,不管这个对象是否拥有类型T的有效值,如果将该对象的底层字节序列复制到一个字符数组(或者无符号字符数组)中,再将其复制回对象,那么该对象的值与原始值一样。考试就到

  对于任意的POD类型T,如果两个T指针分别指向两个不同的对象obj1和obj2,如果用memcpy库函数把obj1的值复制到obj2,那么obj2将拥有与obj1相同的值。

  简言之,针对POD对象,其二进制内容是可以随便复制的,在任何地方,只要其二进制内容在,就能还原出正确无误的POD对象。对于任何POD对象,都可以使用memset()函数或者其他类似的内存初始化函数。

核心语言建构期表现的加强

外部模板

  在标准C++语言中,如果在某一个编译单元中编译器碰到一个参数完全指定的模板,它就必须实例化该模板。这种做法可能大大延长编译时间,尤其在许多编译单元使用同样的参数实例化该模板时。

  C++0x将引入外部模板的概念。C++已经拥有了迫使编译器在某一地点实例化模板的语法:

  template class std::vector<MyClass>;

  C++所缺乏的是防止编译器具现化某个模板的能力。C++0x只是简单地将语法扩展为:

  extern template class std::vector<MyClass>;

  这段代码将告诉编译器不要在这个编译单元实例化此模板。

核心语言使用性的加强

初始化列表

  标准C++语言从C语言中借入了初始化列表概念。根据这一概念,结构或数组可以通过给定一串按照结构中成员定义的次序排列的参数来创建。初始化列表可以递归创建,因此结构数组或包含其他结构的结构也能使用初始化列表。这对于静态列表或用某些特定值初始化结构而言非常有用。C++语言中存在能让对象初始化的构造器特性。但构造器特性本身并不能取代初始化列表的所有功能。标准C++允许类和结构使用初始化列表,但它们必须满足POD的定义。非POD的类不能使用初始化列表,一些C++式的容器如std::vector和boost::array也不行。

  C++0x将把初始化列表绑定为一种名为std::initializer_list的类型。这将允许构造器及其他函数接受初始化列表作为其参数。比如:


 new 对象加括号和不加括号的区别

发表于2015/7/16 10:40:11  489人阅读

分类: c/c++编程

在new对象的时候有加上(),有不加(),不知道这个到底是什么区别?

比如:

  1. CBase *base = new CDerived();  
  2. CBase *base = new CDeviced;  

很多人都说,加括号调用没有参数的构造函数,不加括号调用默认构造函数或唯一的构造函数。这是有问题的。

对于自定义类类型:

       如果该类没有定义构造函数(由编译器合成默认构造函数)也没有虚函数,那么class c = new class;将不调用合成的默认构造函数,而class c = new class();则会调用默认构造函数。

       如果该类没有定义构造函数(由编译器合成默认构造函数)但有虚函数,那么class c = new class;和class c = new class();一样,都会调用默认构造函数。

       如果该类定义了默认构造函数,那么class c = new class;和class c = new class();一样,都会调用默认构造函数。

 

对于内置类型:

       int *a = new int;不会将申请到的int空间初始化,而int *a = new int();则会将申请到的int空间初始化为0

 以下两个语句的区别是:第一个动态申请的空间里面的值是随机值,第二个进行了初始化,里面的值为0:

    1. int *p1 = new int[10];    
    2. int *p2 = new int[10]();    

结论:别使用不带括号的new。

  1. class A{  
  2. public:  
  3. //A(){a=1;}   
  4. public:  
  5. int a;  
  6. };  
  7. A *a1=new A;  
  8. A *a2=new A();  
  9.   
  10. cout<<a1->a<<endl; //输出:-842150451   
  11. cout<<a2->a<<endl; //输出0   
  12. A a3;  
  13. cout<<a3.a<<endl; //运行异常,a没有初始化。  

如果加上一个virtual,如virtual ~A(){},

  1. cout<<a1->a<<endl; //输出:-842150451   
  2. cout<<a2->a<<endl; //输出 -842150451  

-------------下面是网上找的帖子,对理解上面的现象可能会有帮助-------------------

一个类满足下列其中任何一个条件:
1.包含了一个类的对象,这个对象有一个构造函数(包括编译器合成的默认构造函数)
2.如果继承自一些基类,其中某些基类有一个构造函数(包括编译器合成的默认构造函数)
3.有一个虚函数,或者继承到了虚函数
4.有虚基类

如果这个类没有默认的构造函数,编译器就会合成一个默认的构造函数,分别做以下事情
如果这个类有构造函数,编译器就会扩张所有构造函数,做以下事情
1.调用这个对象的构造函数
2.调用基类的构造函数
3.设置正确的虚函数表指针
4.设置指向虚基类对象的指针





 先把结论放上来:

  1.  加括号调用没有参数的构造函数,不加括号调用默认构造函数或唯一的构造函数,看需求
  2.  C++在new时的初始化的规律可能为:对于有构造函数的类,不论有没有括号,都用构造函数进行初始化;如果没有构造函数,则不加括号的new只分配内存空间,不进行内存的初始化,而加了括号的new会在分配内存的同时初始化为0。

 

以下代码:

#include <iostream>

using namespace std;

int main()
{
    int *a=new int[1000];
    for(int i=0;i<1000;i++){
        a[i]=i+1;
    }
    delete[] a;
    int *b=new int[1000];
    for(int i=0;i<100;i++){
        cout<<b[i]<<endl;
    }

    return 0;
}

没有初始化,输出的结果是:

9437380

9443448

3

4

5

6

。。。

可见,new操作符并没有对内存进行初始化。

而稍微改变一下代码(在new之后添加括号()):

#include <iostream>

using namespace std;

int main()
{
    int *a=new int[1000];
    for(int i=0;i<1000;i++){
        a[i]=i+1;
    }
    delete[] a;
    int *b=new int[1000]();
    for(int i=0;i<100;i++){
        cout<<b[i]<<endl;
    }

    return 0;
}

输出结果为:

0

0

0

0

。。

可见,已经进行了初始化。

 =============================================================================

进一步思考:

定义类A:

class A{
public:
    int a;
    A():a(10){};
};

main函数中使用语句:

    A *b=new A;
    cout<<b->a<<endl;

    A *b=new A();
    cout<<b->a<<endl;

输出结果都是10,可见都进行了初始化。

但是,如果吧A的构造函数删掉,则两个语句输出的结果分别是:随机数,0。

 

由此可见,C++在new时的初始化的规律可能为:对于有构造函数的类,不论有没有括号,都用构造函数进行初始化;如果没有构造函数,则不加括号的new只分配内存空间,不进行内存的初始化,而加了括号的new会在分配内存的同时初始化为0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值