C++ 中的 new 与 *new

Posted

技术标签:

【中文标题】C++ 中的 new 与 *new【英文标题】:new vs *new in C++ 【发布时间】:2013-05-28 14:45:47 【问题描述】:

我这样做:

MyClass myObject = *new MyClass();

但是很多人说我应该这样做:

MyClass *myObject = new MyClass();

是否存在性能差异。还是完全使用第二种方法的合乎逻辑的理由?我只是更喜欢使用第一种方法来摆脱指针混淆。

【问题讨论】:

我的问题是“你为什么要这样做?”如果你想喝一杯水,你是不是先去买一个新杯子,装满水,把水倒进旧杯子里,然后把新杯子扔掉? 哇...我很震惊有人让你用第一种方法逃脱。那只是Babytown的嬉戏。 Nik 的比喻恰到好处。 如果您曾经交过包含此类代码的作业,您应该认真要求退款。他们显然没有抓住它,或者没有有效地解释它的作用以及为什么你不应该这样做。 @NikBougalis:很好的比喻,但他更糟糕:他不会把杯子扔掉;他忘记了它在桌子上的某个地方。我想知道房子里有多少个眼镜! @JimFred RVO is only allowed to happen when the copy constructor is viable 【参考方案1】:

两者都不一样! 首先给你一个未定义的行为[Ref 1:] 或内存泄漏,而如果你稍后调用delete,第二个不会。

MyClass myObject = *new MyClass();

在freestore 上分配MyClass 类型的对象,然后将该对象复制到myObject。您丢失了指向动态分配对象的指针,因此永远无法释放它。 如果MyClass 析构函数有副作用,而你的程序依赖于这些副作用,那么它会给你未定义的行为,如果没有,那么你所拥有的只是一个简单的内存泄漏

MyClass *myObject = new MyClass();

在freestore 上分配MyClass 类型的对象,并将myObject 指向放置动态分配对象的地址。您仍然拥有指向该对象的指针,您可以稍后通过调用 delete 来解除分配。


如果您的问题是,最好的方法是什么, 答案是根本不使用动态分配的对象:

MyClass obj;

好读:

Why should C++ programmers minimize use of 'new'?


[参考 1:]C++11 标准:3.8.4:

程序可以通过重用对象占用的存储空间或通过显式调用具有非平凡析构函数的类类型对象的析构函数来结束任何对象的生命周期。对于具有非平凡析构函数的类类型的对象,在重用或释放对象占用的存储空间之前,程序不需要显式调用析构函数;但是,如果没有明确调用 析构函数或如果删除表达式 (5.3.5) 不用于释放存储,不应隐式调用析构函数,并且任何依赖于析构函数产生的副作用的程序具有未定义的行为。强>

【讨论】:

为什么在析构函数中释放具有副作用的堆分配对象会产生未定义的行为? ***.com/questions/1978709/… @AlexB:因为标准明确说明了这一点。添加了报价供您参考。此外,这是一种非常直观的行为,例如,在析构函数中关闭文件句柄或描述符,这些文件句柄或描述符永远不会被调用,那么 UB 肯定是打开的。 如果程序依赖析构函数的副作用,它只是UB,但这实际上只是一个重言式。仅仅因为析构函数可能副作用,如果它们被忽略,那么泄漏内存就是泄漏内存。 @LeeDanielCrocker:我已经添加了标准中的确切引用来指定这一点。它说得很清楚,即使我的措辞可能不那么清楚。【参考方案2】:

第一个例子说:在堆栈上为 MyObject 的一个实例分配内存,然后在堆上为另一个分配内存,在堆上构造一个,将其内容复制到堆栈上的一个,然后丢失轨道堆指针,所以它不能被释放。

第二个说:在堆栈上分配一个指针,在堆上为 MyObject 的实例分配空间,构造它,并将指针分配给它的地址,以便以后可以释放它。

第二种情况使用更少的内存,速度更快,并且不会泄漏内存。第一个案例说“我不懂 C++”。

【讨论】:

【参考方案3】:

第一个是废话。

MyClass myObject = *new MyClass();

= 之后的部分分配内存并创建一个新的MyClass 对象。 第一部分通过使用 RHS MyClass 对象调用复制构造函数来创建一个新的 MyClass 对象。然后在 RHS 中分配的内存泄漏,因为您没有保存的指针来删除它。

上面的说法和写法一样。

MyClass myObject;

紧随其后

Leak memory equal to size of MyClass.

首先决定你想要一个对象在栈上还是堆上。

如果你想要一个对象在堆栈上,那么做

MyClass myObject;

这会创建一个 MyClass 对象 - 它适用于大多数用途。

如果你需要堆上的对象,那么做

MyClass *myObject = new MyClass();

第一种方式 - 在堆栈上分配更有效。您出于其他原因进行堆分配

    在编译时,您不知道需要创建多少对象。 多态地使用类。

【讨论】:

不一样 - 要求复制构造函数至少可见并且它可能会被调用,而 MyClass myObject; 始终只是默认构造的。 我想编辑和更改“废话”(它会编译,它会做一些事情,并且在某个地方会有一些疯子实际上设计了一个系统,以某种方式要求你做一些完全类似的事情,可能网络人)到“无价”,“喜剧黄金”,“retardarific”,“herptastic”。 我认为废话太强了,但我也不会称之为有趣(或类似的词)。使用设计不良的类可能是“正确”的,但在通常情况下,它会泄漏内存并且不是预期的。如果它是有意的,你至少也需要一个很好的解释性评论。 程序后面只要用delete &myObject就可以用MyClass& myObject = *new MyClass();吗?

以上是关于C++ 中的 new 与 *new的主要内容,如果未能解决你的问题,请参考以下文章

C++中new出得对象与C中的malloc出得有啥联系和区别?

C++内存分配方法new与placement new使用方法详解

c++中的关键字new是什么东西?

c++中的new()申请二维数组

C++ 中的 new/delete 和 new[]/delete[]深入理解

C++ 中的 new/delete 和 new[]/delete[]深入理解