Does new always allocate on the heap in C++ / C# / Java

15,978

Solution 1

I thought that new is only needed for reference types (classes), and that primitive types (int, bool, float, etc.) never use new

In C++, you can allocate primitive types on the heap if you want to:

int* p = new int(42);

This is useful if you want a shared counter, for example in the implementation of shared_ptr<T>.

Also, you are not forced to use new with classes in C++:

void function()
{
    MyClass myObject(1, 2, 3);
}

This will allocate myObject on the stack. Note that new is rarely used in modern 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.

Solution 2

I don't know precisely about Java (and it seems quite difficult to get a documentation about it).

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).aspx for more details.

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.

Solution 3

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.

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 widespread implementation 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.)

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.

Example: What the C# specification says about operator new:

Note how the following part of the C# specification published by ECMA (4th edition) does not mention any "stack" or "heap":

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.

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 does say, 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". That is the important thing to understand, not the "heap" or the "stack"!

Solution 4

In c#, a class always lives on the heap. A struct can be either on the heap or stack:

  • variables (except captures and iterator blocks), and fields on a struct that is itself on 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

Solution 5

(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:

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 autoboxing rules? Also see this question for more details on autoboxing. Check out comments on this answer for exceptions to the rule where primitives are allocated on the heap.

Share:
15,978
Alex
Author by

Alex

Updated on June 15, 2022

Comments

  • Alex
    Alex almost 2 years

    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 information that makes me doubt this long standing assumption, at least for Java and 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?

    Can someone please clarify this?

  • Alex
    Alex almost 13 years
    I was aware that Integer is a reference type and int is the primitive, but thank you for helping.
  • Jagannath
    Jagannath almost 13 years
    what's wrong with the answer ? Just wanted to know. No issues with the downvote.
  • Dhruv Gairola
    Dhruv Gairola almost 13 years
    I don't know about c#, but in Java 6, something like int myInt = new int() will not compile.
  • configurator
    configurator almost 13 years
    In Java primitives aren't allocated on the stack if they're fields, only if they're locals. In C# structs are allocated on the stack if they're locals or method parameters and they are not hoisted into lambda closures. I'm pretty sure there were other cases that cause a value type to go on the heap but I can't think of any right now.
  • Marc Gravell
    Marc Gravell almost 13 years
    In c# it is not true that "new" always returns a reference to an object on the heap, nor that such is tied to GC
  • Marc Gravell
    Marc Gravell almost 13 years
    In c# primitives can very much live on the heap - I've covered the scenarios in my answer
  • configurator
    configurator almost 13 years
    Oh! Iterator blocks. They hoist all their locals into the heap as well.
  • Marc Gravell
    Marc Gravell almost 13 years
    @configuration iterator blocks, boxes, arrays.
  • Kerrek SB
    Kerrek SB almost 13 years
    Silly question: Does C# (the langauge) actually have a notion of "stack" and "heap"? I've checked the standard (first edition) and couldn't find any reference to it, and neither is there one on the OP's linked MS website. C++ definitely does not prescribe any particular memory implementation.
  • Alexandre C.
    Alexandre C. almost 13 years
    @Kerrek SB: MSDN explicitly states "heap" and "stack" in their C# article about new. I know this isn't an ECMA document, but since they make the language and are the reference implementation/documentation, this means to me there is a stack and heap in C#.
  • stakx - no longer contributing
    stakx - no longer contributing almost 13 years
    Relevant articles from Eric Lippert's blog: The Stack Is An Implementation Detail, Part 1 and Part 2.
  • Alex
    Alex almost 13 years
    Thanks. What's used instead of new in modern c++?
  • Kerrek SB
    Kerrek SB almost 13 years
    @stakx: Thanks! Alex: this is sort of worrying. Why does MS go to these troubles of getting a standard pushed through if they're the only thing people are supposed to think about? Is there no merit in discussing C# abstractly? (I guess SO doesn't have a dedicated "MS-C#" tag...)
  • stakx - no longer contributing
    stakx - no longer contributing almost 13 years
    @Alexandre, Eric Lippert (who, I trust, knows his stuff) mentions in one of the articles on his blogs that it's unfortunate that MSDN often talks in terms of "stack" and "heap" explicitly, because (IIRC) the relevant specifications don't actually require these. They should be considered as an implementation detail. See e.g. the articles I linked to.
  • Kerrek SB
    Kerrek SB almost 13 years
    Annoyingly, while you can say int i = new int() in C#, you cannot say new int(1) -- this is a sort of anaemic pseudo-construct that is baffling to me, me coming from C++... I'm currently trying to get into C#, but those sort of things strike me as not thought-out.
  • Alexandre C.
    Alexandre C. almost 13 years
    @stakx: thanks for the links. However, as Kerrek points out, this is something they shouldn't worry too much about.
  • Alexandre C.
    Alexandre C. almost 13 years
    @Kerrek SB: The fact that new int() gives you an "automatic storage" integer really annoys me. This is not consistent with anything.
  • Kerrek SB
    Kerrek SB almost 13 years
    @Alex: I'm sorry if I wasn't clear, I do think this is a very regrettable confusion, and I fully agree with Lippert's articles that it would have been better to describe the language clearly! (And in fact, as he says, not all value types are actually put on the stack!)
  • fredoverflow
    fredoverflow almost 13 years
    Well, new has many different uses in C++... instead of new char[n], you use std::string. Instead of new MyClass[n], you use std::vector<MyClass>. If you want to share objects, instead of MyClass* p = new MyClass you use auto p = make_shared<Class>() etc.
  • Alex
    Alex almost 13 years
    Please suggest this to the interviewers that are asking me heap vs stack questions in C# :)
  • stakx - no longer contributing
    stakx - no longer contributing almost 13 years
    -1 for linking to MSDN when explaining C#'s behaviour, but referring to a standards document for C++'s behaviour. If you had looked at the C# standard, you wouldn't have seen any mention of a "stack" connected to operator new.
  • Alexandre C.
    Alexandre C. almost 13 years
    @stakx: the de facto authoritative reference for C# is msdn. The authoritative reference for C++ is the standard document, by lack of a consensus implementation. But undoubtedly you are right: microsoft cannot document their language properly.
  • stakx - no longer contributing
    stakx - no longer contributing almost 13 years
    @Alex, agreed with your last statement. Still, the C# standard is more useful in this case (IMHO) because it uses the proper mindset for thinking about the language; MSDN suggests a inappropriate way of thinking. Hopefully the -1 doesn't seem too harsh, it's only given in the spirit of a good argument.
  • Arjan Tijms
    Arjan Tijms almost 13 years
    Java 6 actually has escape analysis as well. It was introduced in I think u14 as an option and made the default in a later update. There even has been a specific performance build (around u7 orso) that did escape analysis.
  • Kerrek SB
    Kerrek SB almost 13 years
    You probably meant the "placement-new expression", not the operator (the operator is in fact a no-op). The crucial feature of the new expression is calling a constructor.
  • Deqing
    Deqing almost 9 years
    I'd say delete is rarely used in modern C++. We might use new for shared_ptr or unique_ptr in some circumstances.
  • fredoverflow
    fredoverflow almost 9 years
    @Deqing Why? We have make_shared and make_unique.
  • Deqing
    Deqing almost 9 years
    @fredoverflow when you don't want weak_ptr to keep the shared count from deleted.