没有新的C ++对象


77

这是一个非常简单的问题,但是我好几年都没有正确地完成c ++的工作,所以对此我感到有些困惑。另外,在互联网上查找(而不是尝试)不是最简单的事情(至少对我而言)。

为什么不使用new关键字,它如何工作?

基本上,这是怎么回事?

CPlayer newPlayer = CPlayer(position, attacker);

Answers:


65

该表达式:

CPlayer(position, attacker)

CPlayer使用上述构造函数创建一个临时类型的对象,然后:

CPlayer newPlayer =...;

使用复制构造函数将提到的临时对象复制到newPlayer。更好的方法是编写以下代码以避免临时使用:

CPlayer newPlayer(position, attacker);

7
实际上,编译器可能会对其进行优化。在这种情况下,不会调用复制构造函数。stackoverflow.com/questions/1758142/…–
BostonLogan

5
声明中的赋值与使用构造函数语法一样有效。如果它们是分开的陈述,那么关于临时性的评论将是正确的。实质是,它声明了一个CPlayer(通常在堆栈上),而不是从免费存储(堆)中为其分配空间。
阿德里安·麦卡锡

1
不,几乎是按定义的:堆栈中的对象仅在范围内才存在。stackoverflow.com/search?q=%5Bc%2B%2B%5D+stack+heap
Josh Lee,2009年

1
我认为这个答案不正确。OP的代码看起来像是使其成为一个临时文件,然后将其复制,但是标准12.1.11则相反。这只是jleedev发现的普通构造函数调用。
Michael Kristofik,

9
是否取消副本(在允许的情况下)由编译器决定。12.8 / 15。
史蒂夫·杰索普

55

上面的代码在堆栈上构造了一个CPlayer对象,因此不需要new。仅new在尝试在堆上分配CPlayer对象时才需要使用。如果使用堆分配,则代码如下所示:

CPlayer *newPlayer = new CPlayer(position, attacker);

请注意,在这种情况下,我们使用的是指向CPlayer对象的指针,该指针需要通过对的匹配调用来清理delete。当超出范围时,分配在堆栈上的对象将被自动销毁。

实际上,这样写起来会更容易和更明显:

CPlayer newPlayer(position, attacker);

无论如何,许多编译器都会优化您发布到上面的版本,并且阅读起来更加清晰。


2
我认为这是不对的:“分配给堆的对象超出范围时将被自动销毁。”
Valentin

1
您是对的,我的意思是写“堆栈”,而不是“堆”。感谢您指出了这一点。
Timo Geusch 2013年

对此表示同意。我们应该保持C ++代码与C代码相同的样式。因此CPlayer newPlayer(position, attacker);CPlayer newPlayer = CPlayer(position, attacker);要创建堆栈变量更好。
tonga 2013年

10
CPlayer newPlayer = CPlayer(position, attacker);

此行创建一个类型为CPlayer的新本地对象。尽管外观类似于函数,但这只是调用CPlayer的构造函数。不涉及临时性或复制。名为newPlayer的对象的生存时间与包含在其中的作用域一样长。new此处不使用关键字,因为C ++不是Java。

CPlayer* newPlayer = new CPlayer(position, attacker);

此行在堆上构造一个CPlayer对象,并定义一个名为newPlayer的指针指向该对象。该对象一直存在,直到有人抓到为止delete


3
“不涉及临时性或复制性”-这并非完全正确。没有这样的保证。但是每个好的编译器都应该删除副本。
sellibitze

6

newPlayer不是动态分配的变量,而是自动的,堆栈分配的变量:

CPlayer* newPlayer = new CPlayer(pos, attacker);

与...不同

CPlayer newPlayer = CPlayer(pos, attacker);

newPlayer是通过常规CPlayer(position,Attacker)构造函数调用在堆栈上分配的,尽管比通常情况有些冗长

CPlayer newPlayer(pos, attacker);

基本上与说相同:

int i = int(3);

2
小心点 这是“复制初始化”。这不是一项任务。
sellibitze

我的立场是正确的,这不是任务。甚至拷贝构造函数都没有涉及。相应地编辑答案。
digitalarbeiter

2
当然,(至少在逻辑上)涉及复制控制器。您会注意到,如果将复制ctor设为私有。然后,此副本初始化将不再起作用。即使编译器能够优化副本,C ++标准也需要可访问的副本控制器。
sellibitze

不,新分配在堆上,您的第二个玩家在堆栈上思考
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.