我的理解一直是,无论使用C ++或C#还是Java,当我们使用new
关键字创建对象时,它会在堆上分配内存。我认为new
只需要引用类型(类),而原始类型(int,bool,float等)从不使用new
并且总是进入堆栈(除非它们' re一个用new
实例化的类的成员变量。但是,我一直在阅读information让我怀疑这个长期存在的假设,至少对于Java和C#而言。
例如,我刚注意到在C#中new
运算符可用于初始化值类型,请参阅here。这是规则的一个例外,该语言的辅助功能,如果是,那么还会有哪些其他例外?
有人可以澄清一下吗?
答案 0 :(得分:25)
我认为引用类型(类)只需要new,而原始类型(int,bool,float等)从不使用new
在C ++中,如果要执行以下操作,可以在堆上分配基元类型:
int* p = new int(42);
如果你想要一个共享计数器,这很有用,例如在shared_ptr<T>
。
此外,您不必在C ++中使用new with class:
void function()
{
MyClass myObject(1, 2, 3);
}
这将在堆栈上分配myObject
。请注意,new
在现代C ++中很少使用。
此外,您可以在C ++中重载operator new
(全局或特定于类),因此即使您说new MyClass
,该对象也不一定会在堆上分配。
答案 1 :(得分:8)
我不完全了解Java(并且很难获得有关它的文档)。
在C#中,new
调用构造函数并返回一个新对象。如果它是值类型,则在堆栈(例如,局部变量)或堆上分配(例如,盒装对象,引用类型对象的成员)。如果它是引用类型,它总是在堆上并由垃圾收集器管理。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/fa0ab757(v=vs.80).aspx。
在C ++中,“new expression”返回一个指向具有动态存储持续时间的对象的指针(即你必须自己销毁)。在C ++标准中没有提到堆(具有这个含义),并且获得这样一个对象的机制是实现定义的。
答案 2 :(得分:7)
无论使用C ++或C#还是Java,我的理解始终是当我们使用
new
关键字创建对象时,它会在堆上分配内存。
您的理解不正确:
new
可能在不同的编程语言中有所不同,即使这些语言表面上相似也是如此。不要让C#,C ++和Java的类似语法误导你!
术语“堆”和“堆栈”(因为它们在内部存储器管理的上下文中被理解)与所有编程语言无关。可以说,这两个概念更多的是实现细节,而不是编程语言官方规范的一部分。
(IIRC,至少C#和C ++都是如此。我不了解Java。)
它们是广泛实施细节的事实并不意味着您应该依赖于这种区别,也不应该知道它! (但是,我承认我通常发现在内部了解“事情如何运作”是有益的。)
我建议你不要过于担心这些概念。你需要做的正确的重要事情是理解语言的语义;例如,对于C#或任何其他.NET语言,引用和值类型语义的差异。
new
的内容:请注意C# specification published by ECMA (4th edition)的以下部分未提及任何“堆栈”或“堆”:
14.5.10新运算符
new运算符用于创建类型的新实例。 [...]
new运算符意味着创建一个类型的实例,但不一定意味着动态分配内存。特别是,值类型的实例除了它们所在的变量之外不需要额外的内存,并且当使用new来创建值类型的实例时,不会发生动态分配。
相反,它谈到“动态分配内存”,但这不是一回事:你可以动态地在堆栈上,堆上或其他任何地方(例如在硬盘驱动器上)分配内存
然而, 所做的是指,值类型的实例是就地存储的,这正是值类型语义的全部内容:值类型实例在赋值期间被复制,而引用类型实例被引用/“别名”。 那是理解的重要事情,而不是“堆”或“堆栈”!答案 3 :(得分:3)
在c#中,class
总是存在于堆上。 struct
可以在堆或堆栈上:
答案 4 :(得分:2)
(参考Java)你说的是正确的 - 在栈上分配原语(有例如闭包)。但是,您可能指的是以下对象:
Integer n = new Integer(2);
这是指一个Integer对象,而不是一个原始int。也许这是你混乱的根源?在这种情况下,n将在堆上分配。也许你的困惑是由于autoboxing规则造成的?有关自动装箱的详细信息,另请参阅this问题。查看对此答案的评论,以了解在堆上分配基元的规则的例外情况。
答案 5 :(得分:2)
根据http://download.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html,Java 7执行转义分析以确定是否可以在堆栈上分配对象。
但是,您无法指示运行时在堆或堆栈上分配对象。它是自动完成的。
答案 6 :(得分:2)
关于c#,请阅读The Truth About Value Types。 您将看到值类型也可以在堆上。
建议at this question引用类型可以进入堆栈。 (但目前不会发生)
答案 7 :(得分:0)
在Java和C#中,我们不需要在堆上分配原始类型。它们可以在堆栈上分配(而不是它们被限制为堆栈)。然而,在C ++中,我们可以在堆栈和堆上分配原始类型和用户定义类型。
答案 8 :(得分:0)
在C ++中,还有另一种使用新运算符的方法,那就是通过新的&#39;放置新的&#39;。你指向的记忆可以存在于任何地方。