Foo f1 = Foo(); // (1) Ok
Foo f2 = Foo; // (2) Compiler error
Foo *p1 = new Foo(); // (3) Ok
Foo *p2 = new Foo; // (4) Ok. Why??
我想知道为什么存在两种初始化指针的方法。看起来有点不协调。有什么合乎逻辑的原因吗?如果有,是什么原因?或者,也许这是某种遗产?如果是这样,这种符号的起源是什么?
Foo f1 = Foo(); // (1) Ok
Foo f2 = Foo; // (2) Compiler error
Foo *p1 = new Foo(); // (3) Ok
Foo *p2 = new Foo; // (4) Ok. Why??
我想知道为什么存在两种初始化指针的方法。看起来有点不协调。有什么合乎逻辑的原因吗?如果有,是什么原因?或者,也许这是某种遗产?如果是这样,这种符号的起源是什么?
这有点……复杂,至少可以这么说。
在处理对象时,两种表示法是等价的。在处理原始类型(例如int
)时,(3)
将初始化(零填充)该值,而(4)
不会(该值将未定义)。
对于自动分配的对象,这:
Foo f1;
Foo
使用默认构造函数声明和初始化对象。这:
Foo f2 = Foo();
使用复制构造函数声明并初始化一个对象,本质上是复制一个使用默认构造函数构建Foo
的临时对象 (the ) 的值。Foo()
我告诉你这似乎不合逻辑,但如果你考虑一下可能的含义,那就很有意义了。
在不知道Foo
可能是什么的情况下,无论是人类还是编译器(在这里,人类的视角更重要)都无法确定是否Foo f2 = Foo;
是 a)创建一个新的临时Foo
对象并使用它复制构造另一个对象,或者 b)分配的值Foo
复制构造对象 ( f2
)的变量。这对我们来说似乎很明显,因为我们的约定告诉我们Foo
必须是一个类型,因为它是大写的,但总的来说它不是那么简单(再次强调:这主要适用于不一定记住整个源代码的人类读者) .
(2)
和之间的区别在于(4)
,对于后者,只有一种解释是可接受的,因为new var
(where var
is a variable) 不是合法表达式。
基于范围的资源相当于 4 实际上只是
Foo f;
造成差异的遗留原因本质上是在 C 中,原始类型,例如int
,没有默认初始化为有用的东西。出于性能原因,C++ 在当时继承了这种行为。当然,现在,要花费的处理器时间是微不足道的。在 C++ 中,他们引入了一种新的语法,它总是会被初始化——括号。
int i = int();
i
始终保证为 0。
int i;
的值i
未定义。
这与指针种类完全相同,只是有一些new
:
int* i = new int(); // guaranteed 0
int* i = new int; // undefined