对象和实例的区别:C++

10

我在stackoverflow上跟了很多帖子,最后得出结论,当我们遇到下面这种情况时:

Person name;

nameperson 类的一个对象。

当实例化它时,它变成一个实例:

name=new Person();

我是一名C++初学者,目前我了解到我们可以像这样访问函数和变量:
Person name;
name.getValue;
name.callFunction();

我们不需要使用 new 操作符。那么我们可以说,在C++中,对象和实例之间的区别可以被忽略吗?

1
请参阅 https://dev59.com/7mkw5IYBdhLWcg3wEmab 了解有关在堆栈或堆上创建对象的信息。 - SolarBear
在C++中,对象是存储区域。 - chris
术语“对象”和“实例”是可以互换的。new创建一个堆分配的对象,没有自动存储期。operator new()的返回类型是指针。 - Sebastian Hoffmann
5个回答

14
在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是“模板实例化和特化”,而实例化点(模板的)是标准中的所有正式术语。

我已经在C++11草案中搜索过了。单词“instance”只出现了几次(大多数是在“例如”中 :))。我认为你的观点很有趣,我可能会使用相同的术语,但你能指出标准中实际讨论“引用类型的实例”的地方吗? - Christian Hackl
1
@ChristianHackl 不好意思,标准似乎没有通用地讨论非对象类型的实例。它只涉及对象和引用,但我找不到标准中用于“类型的实例”的通用术语... - Yakk - Adam Nevraumont

8
首先,您应该知道“对象”和“实例”之间没有区别。它们是同义词。在C++中,您还可以将原始类型的实例(如intdouble)称为“对象”。C++的设计原则之一是可以使自定义类型(即类)的行为与原始类型完全相同。实际上,在C++中,人们通常更喜欢引用“类型”,而不是“类”。
所以,现在我们使用“类型”和“对象”这两个术语。既然我们解决了这个问题,我恐怕必须告诉您,您的结论是错误的。 Person是一个“类型”。 name是一个(命名不太好的)变量,用于访问该类型的一个“对象”。
一整行C++代码看起来像这样:
Person name;

这意味着:“创建一个名为Person的对象,并让我通过name变量访问它”。相比之下,new Person()则更加复杂。你可能对类似Java这样的语言中的new关键字很熟悉,但在C++中,它是完全不同的东西。它表示创建一个类型为Person的新对象,但还意味着你后面需要负责销毁它。同时,它也给了你一个新建立的对象的不同类型的句柄:所谓的指针。指向Person的指针看起来像这样:
Person*

指针本身是一种类型,而类型“Person*”和“Person”不兼容。(我告诉过你这会更加复杂:))
当您尝试编译以下行时,您将注意到不兼容性:
Person name = new Person();

它无法编译,您会收到错误消息。您必须像这样做:

Person* name_ptr = new Person();

然后您将需要使用不同的语法访问Person的所有成员:

name_ptr->getValue();
name_ptr->callFunction();

最后,记得在这种情况下必须显式销毁对象:
delete name_ptr;

如果你忘记了这一点,可能会发生糟糕的事情。更确切地说,你的程序在运行越久,很可能会使用越来越多的内存。

我认为对于你的C++水平来说,指针还太过高级。在你真正需要它们之前,请远离它们。


那么对象和实例之间绝对没有任何区别吗? - joey rohan
2
没错,实际上没有任何区别。可以参考一下isocpp.org上的这个常见问题解答:http://isocpp.org/wiki/faq/classes-and-objects#overview-object - Christian Hackl

5

对象和实例是表示同一个东西的两个词。


1
此外,您应该始终使用“实例”一词。因此,某个对象是某个类的实例。 - DSquare
@DSquare:这是有争议的。你会发现许多C++程序员谈论“对象”。如果我没记错,这也是标准中首选的术语(如果我错了,请纠正我)。 - Christian Hackl
@ChristianHackl 我并不是说你应该总是使用“instance”,我是在说如果你使用“instance”,那么你所表达的意思就是“[class]的实例”的简称。而我们知道,一个类的实例就是一个对象。因此,“instance”等同于“object”。 - DSquare

2
"

对象(Object)和实例(Instance)几乎可以互换。在C++中,对象(formally)是存储区域的任何一部分。"实例"并没有一个正式定义的术语,但我们通常指的是“类型为X的实例”,最常用于类类型。

"
Foo f;

这个声明创建了一个名为f的对象。该对象的类型是Foo。你可以说对象fFoo的一个实例。

你试图区分这两个术语的尝试是不正确的。你实际上指出的是创建对象的两种不同方式。

Person name;

在这个例子中,我们正在创建一个类型为Person的对象name

Person* name = new Person();

在这种情况下,我们正在创建一个类型为Person*(指向Person的指针)的对象name。我们还使用表达式new Person()创建了另一个Person类型的对象。该表达式返回一个指针,我们将其用于初始化name对象。

我所理解的是,如果我们使用Java而不是C ++,那么这样做是否正确? - joey rohan
@joeyrohan 不是,但“instance”更多地是Java术语。在Java中,人们倾向于谈论“X的实例”而不是“类型为X的对象”。 - Joseph Mansfield

2

这很简单但非常重要

举个通俗的例子:对象的一般意义是什么?不就是占用一些空间吗...记住这一点,我们现在谈论Java或C++中的对象

例如:我在这里创建对象 Student std = new Student();

其中Student是一个,而std是一个对象,因为我们使用new关键字为std创建了内存,这意味着它在内存中占用了一些空间,所以我们将std称为对象

如果您不为对象创建内存,那么我们将其称为实例

例如:Student std;

这里Student是一个类,std是一个实例(只是该类的一个副本),在这种情况下,除非我们为其创建内存,否则我们将不会做任何事情。

这就是关于对象和实例的全部内容 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接