C++ 类型名称后面的括号与new有区别吗?
如果“测试”是一个普通类,那么以下两者之间是否有任何区别:C++ 类型名称后面的括号与new有区别吗?,c++,constructor,initialization,new-operator,c++-faq,C++,Constructor,Initialization,New Operator,C++ Faq,如果“测试”是一个普通类,那么以下两者之间是否有任何区别: Test* test = new Test; Test t; // create a Test called t 及 不,它们是一样的。但两者之间有区别: Test* test = new Test; Test t; // create a Test called t 及 这是因为基本的C++(和C)规则:如果某个东西可能是一个声明,那么它就是一个声明。 编辑:关于POD和非POD数据的初始化问题,虽然我同意
Test* test = new Test;
Test t; // create a Test called t
及
不,它们是一样的。但两者之间有区别:
Test* test = new Test;
Test t; // create a Test called t
及
这是因为基本的C++(和C)规则:如果某个东西可能是一个声明,那么它就是一个声明。
编辑:关于POD和非POD数据的初始化问题,虽然我同意所说的一切,但我只想指出,这些问题仅适用于新建或以其他方式构造的对象没有用户定义的构造函数的情况。如果有这样一个构造函数,它将被使用。对于99.99%设计合理的类,将有这样一个构造函数,因此可以忽略这些问题 假设Test是一个具有已定义构造函数的类,则没有区别。后一种形式使测试的构造函数正在运行变得更加清晰,但仅此而已。一般来说,第一种情况下我们有默认初始化,第二种情况下有值初始化 例如: 如果为int(吊舱类型):
-我们有任何初始化,并且*test的值可以是任何值int*test=new int
int*test=new int()
我们有不同的情况:测试有defult构造函数,测试生成默认构造函数,测试包含POD成员,非POD成员…让我们学究一点,因为有一些差异实际上会影响代码的行为。下面的大部分内容摘自对一位记者的评论 有时,新操作符返回的内存将被初始化,有时则不初始化,这取决于您正在更新的类型是类型,还是包含POD成员的类,并且使用编译器生成的默认构造函数
- 在C++1998中,有两种类型的初始化:零和默认
- 在C++2003中,添加了第三种类型的初始化,即值初始化
struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m
在C++98编译器中,应发生以下情况:
-不确定值新A
-零初始化新建A()
-默认构造(B::m未初始化)新建B
-默认构造(B::m未初始化)new B()
-默认构造(C::m为零初始化)新建C
-默认构造(C::m为零初始化)newc()
-不确定值新A
-值初始化A,这是零初始化,因为它是一个POD新建A()
-默认初始化(使B::m未初始化)新建B
-值初始化B,其中零初始化所有字段,因为它的默认构造函数是编译器生成的,而不是用户定义的new B()
-默认值初始化C,它调用默认的ctor新建C
-值初始化C,它调用默认的ctornew C()
new B()
,在行为上存在差异
这是C++中的一个满是灰尘的角落,会让你发疯的。在构造对象时,有时你想要/需要这些参数,有时你绝对不能拥有它们,有时这并不重要。newthing()
明确表示您需要一个名为whilenew Thing的构造函数
表示您不介意不调用构造函数
如果在具有用户定义构造函数的结构/类上使用,则没有区别。如果在平凡的结构/类上调用(例如,struct Thing{int i;};
),则新事物
就像malloc(sizeof(Thing))代码>而新事物()
类似于calloc(sizeof(Thing))代码>-初始化为零
问题在于:
struct Thingy {
~Thingy(); // No-longer a trivial class
virtual WaxOn();
int i;
};
新事物的行为代码>vs新事物()在本例中,代码>在C++98和C++2003之间更改。请参阅以了解方法和原因。新建
的规则类似于使用自动存储持续时间初始化对象时发生的情况(尽管由于解析困难,语法可能略有不同)
如果我说:
int my_int; // default-initialize → indeterminate (non-class type)
然后,my_int
有一个不确定的值,因为它是非类类型。或者,我可以像下面这样初始化值my_int(对于非类类型,零初始化):
int my_int{}; // value-initialize → zero-initialize (non-class type)
(当然,我不能使用()
,因为这将是一个函数声明,但是int()
的工作原理与int{}
的工作原理相同,可以构造一个临时函数。)
鉴于,对于类别类型:
Thing my_thing; // default-initialize → default ctor (class type)
Thing my_thing{}; // value-initialize → default-initialize → default ctor (class type)
调用默认构造函数来创建对象
,没有异常
因此,规则或多或少是:
- 这是一种班级类型吗?
- YES:调用默认构造函数,不管它是值初始化(使用
{}
)还是默认初始化(不使用{}
)。(对于值初始化,有一些额外的先前归零行为,但默认构造函数始终拥有最终发言权。)
- 否:是否使用了
{}
?
- 是:对象是值初始化的,对于非类类型,或多或少只初始化零
- 否:对象默认已初始化,对于非类类型,该对象将保留一个不确定的值(实际上未初始化)
这些规则准确地转化为newint* my_new_int = new int; // default-initialize → indeterminate (non-class type)
Thing* my_new_thing = new Thing; // default-initialize → default ctor (class type)
int* my_new_zeroed_int = new int(); // value-initialize → zero-initialize (non-class type)
my_new_zeroed_int = new int{}; // ditto
my_new_thing = new Thing(); // value-initialize → default-initialize → default ctor (class type)