在 C++/C#/Java 中,new 是否总是在堆上分配
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6972111/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Does new always allocate on the heap in C++ / C# / Java
提问by Alex
My understanding has always been, regardless of C++ or C# or Java, that when we use the new
keyword to create an object it allocates memory on the heap. I thought that new
is only needed for reference types (classes), and that primitive types (int, bool, float, etc.) never use new
and always go on the stack (except when they're a member variable of a class that gets instantiated with new
). However, I have been reading informationthat makes me doubt this long standing assumption, at least for Java and C#.
我的理解一直是,无论是 C++、C# 还是 Java,当我们使用new
关键字创建一个对象时,它会在堆上分配内存。我认为这new
仅适用于引用类型(类),并且原始类型(int、bool、float 等)从不使用new
并且总是在堆栈上(除非它们是被实例化的类的成员变量)与new
)。但是,我一直在阅读的信息让我怀疑这个长期存在的假设,至少对于 Java 和 C#。
For example, I just noticed that in C# the new
operator can be used to initialize a value type, see here. Is this an exception to the rule, a helper feature of the language, and if so, what other exceptions would there be?
例如,我刚刚注意到在 C# 中,new
运算符可用于初始化值类型,请参见此处。这是规则的例外,语言的辅助功能,如果是,还会有哪些其他例外?
Can someone please clarify this?
有人可以澄清一下吗?
回答by fredoverflow
I thought that new is only needed for reference types (classes), and that primitive types (int, bool, float, etc.) never use new
我认为只有引用类型(类)才需要 new,而原始类型(int、bool、float 等)从不使用 new
In C++, you can allocate primitive types on the heap if you want to:
在 C++ 中,如果需要,可以在堆上分配原始类型:
int* p = new int(42);
This is useful if you want a shared counter, for example in the implementation of shared_ptr<T>
.
如果您想要一个共享计数器,这很有用,例如在shared_ptr<T>
.
Also, you are not forced to use new with classes in C++:
此外,您不必在 C++ 中对类使用 new:
void function()
{
MyClass myObject(1, 2, 3);
}
This will allocate myObject
on the stack. Note that new
is rarely used in modern C++.
这将myObject
在堆栈上分配。请注意,new
在现代 C++ 中很少使用。
Furthermore, you can overload operator new
(either globally or class-specific) in C++, so even if you say new MyClass
, the object does not necessarily get allocated on the heap.
此外,您可以operator new
在 C++ 中重载(全局或特定于类的),因此即使您说new MyClass
,对象也不一定会在堆上分配。
回答by Alexandre C.
I don't know precisely about Java (and it seems quite difficult to get a documentation about it).
我对 Java 不是很了解(而且似乎很难获得有关它的文档)。
In C#, new
invokes the constructor and returns a fresh object. If it is of value type, it is allocated on the stack (eg. local variable) or on the heap (eg. boxed object, member of a reference type object). If it is of reference type, it always goes on the heap and is managed by the garbage collector. See http://msdn.microsoft.com/en-us/library/fa0ab757(v=vs.80).aspxfor more details.
在 C# 中,new
调用构造函数并返回一个新对象。如果是值类型,则在堆栈(例如局部变量)或堆(例如装箱对象、引用类型对象的成员)上分配。如果它是引用类型,它总是在堆上并由垃圾收集器管理。有关更多详细信息,请参阅http://msdn.microsoft.com/en-us/library/fa0ab757(v=vs.80).aspx。
In C++, a "new expression"returns a pointer to an object with dynamic storage duration(ie. that you must destroy yourself). There is no mention of heap (with this meaning) in the C++ standard, and the mechanism through which such an object is obtained is implementation defined.
在 C++ 中,“新表达式”返回一个指向具有动态存储持续时间的对象的指针(即,您必须自行销毁)。C++ 标准中没有提到堆(具有这个含义),并且通过实现定义了获取此类对象的机制。
回答by stakx - no longer contributing
My understanding has always been, regardless of C++ or C# or Java, that when we use the
new
keyword to create an object it allocates memory on the heap.
我的理解一直是,无论是 C++、C# 还是 Java,当我们使用
new
关键字创建一个对象时,它会在堆上分配内存。
Your understanding has been incorrect:
你的理解有误:
new
may work differently in different programming languages, even when these languages are superficially alike. Don't let the similar syntax of C#, C++, and Java mislead you!The terms "heap" and "stack" (as they are understood in the context of internal memory management) are simply not relevant to all programming languages. Arguably, these two concepts are more often implementation details than that they are part of a programming language's official specification.
(IIRC, this is true for at least C# and C++. I don't know about Java.)
The fact that they are such widespreadimplementation details doesn't imply that you should rely on that distinction, nor that you should even know about it! (However, I admit that I usually find it beneficial to know "how things work" internally.)
new
在不同的编程语言中可能会以不同的方式工作,即使这些语言表面上是相似的。不要让 C#、C++ 和 Java 的类似语法误导您!术语“堆”和“堆栈”(它们在内部内存管理的上下文中被理解)与所有编程语言都不相关。可以说,这两个概念通常是实现细节,而不是编程语言官方规范的一部分。
(IIRC,至少对于 C# 和 C++ 是这样。我不了解 Java。)
它们是如此广泛的实现细节这一事实并不意味着您应该依赖这种区别,甚至您也不应该知道它!(但是,我承认我通常发现了解内部“事情如何运作”是有益的。)
I would suggest that you stop worrying too much about these concepts. The important thing that you need to get right is to understand a language's semantics; e.g., for C# or any other .NET language, the difference in reference and value type semantics.
我建议您不要过多担心这些概念。您需要做对的重要事情是理解语言的语义;例如,对于 C# 或任何其他 .NET 语言,引用和值类型语义的差异。
Example: What the C# specification says about operator new
:
示例:C# 规范对 operator 的说明new
:
Note how the following part of the C# specification published by ECMA (4th edition)does not mention any "stack" or "heap":
请注意ECMA(第 4 版)发布的C# 规范的以下部分如何没有提到任何“堆栈”或“堆”:
14.5.10 The new operator
The new operator is used to create new instances of types. […]
The new operator implies creation of an instance of a type, but does not necessarily imply dynamic allocation of memory. In particular, instances of value types require no additional memory beyond the variables in which they reside, and no dynamic allocations occur when new is used to create instances of value types.
14.5.10 新运算符
new 运算符用于创建类型的新实例。[…]
new 运算符意味着创建一个类型的实例,但不一定意味着动态分配内存。特别是,值类型的实例不需要除了它们所驻留的变量之外的额外内存,并且在使用 new 创建值类型的实例时不会发生动态分配。
Instead, it talks of "dynamic allocation of memory", but that is not the same thing: You could dynamically allocate memory on a stack, on the heap, or anywhere else (e.g. on a hard disk drive) for that matter.
相反,它谈到“内存的动态分配”,但这不是一回事:您可以为此在堆栈、堆或其他任何地方(例如硬盘驱动器)上动态分配内存。
What it doessay, however, is that instances of value types are stored in-place, which is exactly what value type semantics are all about: Value type instances get copied during an assignment, while reference type instances are referenced / "aliased". Thatis the important thing to understand, not the "heap" or the "stack"!
然而,它确实说的是值类型的实例存储在原地,这正是值类型语义的全部内容:值类型实例在赋值期间被复制,而引用类型实例被引用/“别名”。理解这一点很重要,而不是“堆”或“堆栈”!
回答by Marc Gravell
In c#, a class
always lives on the heap. A struct
can be either on the heap orstack:
在 C# 中,aclass
总是存在于堆中。Astruct
可以在堆或堆栈上:
- variables (except captures and iterator blocks), and fields on a struct that is itselfon the stack live on the stack
- captures, iterator blocks, fields of something that is on the heap, and values in an array live on the heap, as do "boxed" values
- 变量(捕获和迭代器块除外),以及本身在堆栈中的结构体上的字段存在于堆栈中
- 捕获、迭代器块、堆上某物的字段和数组中的值都在堆上,就像“装箱”值一样
回答by wimh
Regarding c#, read The Truth About Value Types. You will see that value types can go on the heap as well.
关于 c#,请阅读The Truth About Value Types。您将看到值类型也可以放在堆上。
And at this questionis suggested that reference types couldgo on the stack. (but it does not happen at the moment)
而在这个问题被提出,引用类型可以进入堆叠。(但目前不会发生)
回答by Dhruv Gairola
(Referring to Java) What you said is correct- primitives are allocated on the stack (there are exceptions e.g. closures). However, you might be referring to objects such as:
(指Java)你说的是正确的-原语是在堆栈上分配的(有例外,例如闭包)。但是,您可能指的是对象,例如:
Integer n = new Integer(2);
This refers to an Integer object, and not a primitive int. Perhaps this was your source of confusion? In this case, n will be allocated on the heap. Perhaps your confusion was due to autoboxingrules? Also see thisquestion for more details on autoboxing. Check out comments on this answer for exceptions to the rule where primitives are allocated on the heap.
这是指一个 Integer 对象,而不是一个原始的 int。也许这是你困惑的根源?在这种情况下,n 将分配在堆上。也许你的困惑是由于自动装箱规则?另请参阅此问题以了解有关自动装箱的更多详细信息。查看对这个答案的评论,了解在堆上分配原语的规则的例外情况。
回答by Bruno Reis
Java 7 does escape analysis to determine if an object can be allocated on the stack, according to http://download.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html.
根据http://download.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html,Java7 进行逃逸分析以确定是否可以在堆栈上分配对象。
However, you cannot instruct the runtime to allocate an object on heap or on stack. It's done automatically.
但是,您不能指示运行时在堆或堆栈上分配对象。它是自动完成的。
回答by Jagannath
In Java and C#, we don't need to allocate primitive types on the heap. They can be allocated on the stack ( not that they are restricted to stack ). Whereas, in C++ we can have primitive as well as user defined types to be allocated on both stack and heap.
在 Java 和 C# 中,我们不需要在堆上分配原始类型。它们可以在堆栈上分配(而不是限制在堆栈上)。而在 C++ 中,我们可以在堆栈和堆上分配原始类型和用户定义的类型。
回答by Arjan Tijms
In C++, there's an additional way to use the new operator, and that's via 'placement new'. The memory you point it to could exist anywhere.
在 C++ 中,还有另一种使用 new 运算符的方法,那就是通过“placement new”。你指向它的内存可以存在于任何地方。
See What uses are there for "placement new"?
请参阅“放置新”有什么用途?