C ++原始类型初始化vs.对象初始化

时间:2018-06-19 08:50:01

标签: c++ oop object initialization primitive-types

我很好奇C ++原语内置类型(例如int)是如何与类的对象进行初始化的。

经过研究后,我了解到C ++是一种静态类型语言,意味着类型检查是在编译时完成的,而不是在运行时完成的。这意味着,原始类型是类的对象,并且类型不能更改。

所以在以下对象初始化中有什么不同:

class Foo
{
public:
    int num;
    Foo(int n) : num(n) {}
};

Foo bar(5);
Foo bar2{ 5 };
Foo bar3 = 5;

原始初始化:

int num(5);
int num2{ 5 };
int num3 = 5;

我知道Foo的实例调用构造函数来初始化但是如果它不是一个对象,原始调用或初始化的内容是什么?

此外还有什么从根本上区分Foo& int,除了Foo是"用户定义的蓝图以创建实例"和int是"一个非对象内置类型"。

1 个答案:

答案 0 :(得分:0)

类初始化

对于具有用户定义的构造函数(例如Foo)的类,初始化之间的唯一区别是最后一个(称为 copy-initialization )等效于

Foo bar3 = Foo(5);

也就是说,初始化器表达式被转换为类类型(通过构造器通过),然后从{em> that 初始化bar3。 (直到C ++ 17,这在概念上涉及复制或移动,但是编译器通常会避免这种开销。)

请注意,还有一种语法:

Foo bar4={5};

这称为 copy-list-initialization ,但与没有=的版本唯一的区别是不允许使用explicit构造函数。

结构初始化

这些形式之间没有明显的差异,不足以促使人们拥有它们,因此令人困惑。区别在于容器,广义地解释为包括聚合(简单的类似于C的struct s)。那些支持具有不同含义的{}初始化,这就是构造一个包含 数据的对象,而不是根据其中的 computing 。所以

std::vector<double> a(10,1),b{10,1};

a定义为10个值(分别为1),将b定义为两个值10和1。

已建议使用花括号进行初始化应仅限于此含义,以免造成混淆。

原始初始化

最后,我们有您的int示例。现在应该清楚所有初始化都是可以互换的(除了 list-initialization 禁止缩小转换范围),因为在计算原始值和填充原始值之间没有区别。观察原始类型变量的初始化(或赋值)也没有任何可能:它只是将值提供为抽象机的原子动作。 (编译器知道这一点,并为了提高效率而尽可能多地忽略了这些变量。)

对象

即使一个int是一个对象(从C ++的意义上讲,也不是Java或Python的意义),并且当您拥有一个Foo时,您有两个对象:{{1} }本身及其包含的Foo(与之一起创建和销毁)。因此,您对int num对象的初始化也是两个初始化:外部的组成,内部的(由Foo member-initializer < / em>)。

正是这个额外对象的存在将num(n)Foo区别开来,而不必根据内存布局在操作上定义类:int上允许的操作是总的来说有所不同,因为它与可能包含的任何对象不同