在C++中,“对象”和“实例”几乎可以互换使用。
有一个通用的编程设计模式,即“类”和“实例”。类保存了该类中所有实例的(共同)信息。(并非所有实例的全部信息,而是所有实例共有的信息的子集)
在C++中,当你声明一个“类”或“结构体”时,编译器会生成描述如何创建该“类”的实例、数据布局以及提供一些可以与该“实例”交互的方法(包括销毁)的代码。
“虚拟”方法和继承似乎将一些方法和布局移动到实例中,但数量相当有限。相反,每个实例保存指向“虚拟”类数据的指针。在某些语言中,你可以在运行时替换实例的单个方法,但在C++中不行。
当你创建一个该类或结构的实例时,可以通过堆栈上的自动命名变量(如`Foo f;`),匿名自动命名变量(如`some_function( Foo(17,22) )`),堆上的实例(如`new Foo(17, 22)`),或通过放置`new`(这是`std::vector`和`std::make_shared`创建实例的方式)。
令人困惑的是,在C++中有一个独立的并行类-实例模式 -- 类模板-类。类模板是类,实例化是实例。模板参数和特化指示了在编译时如何“构造”类。对类模板进行模式匹配提供了一定数量的与实例无关的属性(模式中的“类属性”)。 (可以说函数模板-函数是类-实例模式的另一个实例)。
如果你看一下
C++1y proposal for concepts lite,你会看到在C++中对象和实例可能意味着不同的东西。
int x = 0;
int& foo = x;
int* bar = &x;
x
既是一个对象,也是类型int
的一个实例。
foo
是类型int&
的一个实例,但称其为对象可能是错误的!它是一个引用——一个别名,或者是某个对象的不同名称(在这种情况下是x
)。
bar
是指向int
的指针,它是类型int*
的一个实例,称其为对象可能是正确的。
这是一个有用的区别:如果是引用类型,类型不一定表示对象类型。对象类型在许多重要方面与引用类型的行为不同。
现在,有些类型具有“引用语义”,在许多方面它们的行为类似于引用,但实际上是class
。这样的类型的实例更适合称为引用还是对象?在糟糕的情况下,某些实例具有引用和对象语义的混合:这通常是一个不好的迹象。
通过
最新标准中的3.9 [类型],我们有C++中的类型种类。它们描述了一个
对象类型是什么:
类型描述了对象(1.8),引用(8.3.2)或函数(8.3.5)
以及
对象类型是一个(可能带有cv限定符的)类型,它既不是函数类型,也不是引用类型,也不是void类型。
因此,称函数类型或引用类型的"实例"为"对象"似乎是不正确的。请注意,访问函数或引用实例的"表示"基本上是不可能的:引用别名到它们所引用的对象,而使用函数的名称会在一瞬间衰减为指向函数的指针(而指向函数的指针基本上是不透明的句柄,允许您调用它们)。
因此,可以说函数不是实例,引用也不是实例。
第三方面,我们确实谈论到类模板和函数模板的实例化。14.7是“模板实例化和特化”,而实例化点(模板的)是标准中的所有正式术语。
new
创建一个堆分配的对象,没有自动存储期。operator new()
的返回类型是指针。 - Sebastian Hoffmann