我曾认为只有引用类型(类)才需要使用 new,而基本类型(int、bool、float等)从不使用 new。
C++ 中,如果你想的话,也可以在堆上分配基本类型:
int* p = new int(42);
如果你想要一个共享计数器,这很有用,例如在实现shared_ptr<T>
时。
此外,在C++中使用类时并不强制使用new:
void function()
{
MyClass myObject(1, 2, 3);
}
这将在堆栈上分配myObject
。请注意,在现代C ++中很少使用new
。
此外,在C ++中,您可以重载operator new
(全局或特定于类),因此即使您说new MyClass
,对象也不一定会分配在堆上。
delete
很少使用。我们可能会在某些情况下使用shared_ptr
或unique_ptr
的new
。 - Deqingmake_shared
和make_unique
。 - fredoverflowweak_ptr
保留已删除的共享计数时。 - Deqing我对Java并不是十分了解(并且似乎很难找到有关它的文档)。
在C#中,new
调用构造函数并返回一个新对象。如果它是值类型,则分配在堆栈上(例如局部变量)或堆上(例如装箱对象,引用类型对象的成员)。如果它是引用类型,则总是放在堆上,并由垃圾回收器管理。有关更多详细信息,请参见http://msdn.microsoft.com/en-us/library/fa0ab757(v=vs.80).aspx。
在C ++中,"new表达式"返回具有动态存储持续时间的对象指针(即,您必须自己销毁该对象)。在C ++标准中,没有提到堆(具有此含义),获得这样的对象的机制是实现定义的。
int i = new int()
,但你不能说 new int(1)
-- 这是一种无力的伪构造,对我来自C ++ 的人来说令人困惑... 我目前正在努力了解C#,但这些事情让我感觉并没有得到充分的考虑。 - Kerrek SBnew int()
给你一个“自动存储”整数的事实真的很让我烦恼。这与任何东西都不一致。 - Alexandre C.new
操作符相关联的“堆栈”提及。 - stakx - no longer contributingnew
关键字创建对象时,它会在堆上分配内存。new
在不同的编程语言中可能有不同的工作方式,即使这些语言表面上相似。不要让C#、C++和Java的相似语法误导您!
"堆"和"栈"这两个概念(在内部内存管理的上下文中理解)并不适用于所有编程语言。可以说,这两个概念更多地是实现细节,而不是编程语言的官方规范。
(据我所知,至少对于C#和C++是正确的。我不知道Java。)
它们是如此广泛的实现细节的事实并不意味着您应该依赖于这种区别,甚至不需要知道它!(然而,我承认我通常发现了解内部"工作原理"是有益的。)
我建议您不要过多地担心这些概念。你需要正确理解的重要事情是理解一种语言的语义;例如,对于C#或任何其他.NET语言,引用类型和值类型语义的区别。
new
的说明:请注意,ECMA发布的C#规范(第4版)的以下部分没有提到任何"堆"或"栈":
14.5.10 new运算符
new运算符用于创建类型的新实例。[...]
new运算符意味着创建类型的一个实例,但不一定意味着动态分配内存。特别地,值类型的实例除了它们所在的变量之外不需要额外的内存,并且当使用new来创建值类型的实例时不会发生动态分配。
相反,它谈论了"动态分配内存",但那并不是同一回事:您可以在堆、栈或任何其他地方(例如硬盘驱动器)上动态分配内存。
然而,它确实说到值类型的实例是就地存储的,这正是值类型语义的全部内容:值类型实例在赋值期间被复制,而引用类型实例被引用/“别名”。这才是需要理解的重要事情,而不是"堆"或"栈"!
class
总是存在于堆上。一个struct
可以存在于堆或栈上: