16

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?

Haris Hasan
  • 29,856
  • 10
  • 92
  • 122
Alex
  • 9,250
  • 11
  • 70
  • 81

9 Answers9

30

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.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • 6
    Thanks. What's used instead of new in modern c++? – Alex Aug 07 '11 at 10:56
  • 9
    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`. If you want to share objects, instead of `MyClass* p = new MyClass` you use `auto p = make_shared()` etc. – fredoverflow Aug 07 '11 at 11:15
  • I'd say `delete` is rarely used in modern C++. We might use `new` for `shared_ptr` or `unique_ptr` in some circumstances. – Deqing Jul 09 '15 at 00:15
  • 2
    @Deqing Why? We have `make_shared` and `make_unique`. – fredoverflow Jul 09 '15 at 09:38
  • @fredoverflow when you don't want `weak_ptr` to keep the shared count from deleted. – Deqing Jul 10 '15 at 03:38
10

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.

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
  • 4
    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 Aug 07 '11 at 10:38
  • 2
    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. – Kerrek SB Aug 07 '11 at 11:00
  • @Kerrek SB: The fact that `new int()` gives you an "automatic storage" integer really annoys me. This is not consistent with anything. – Alexandre C. Aug 07 '11 at 11:04
  • 1
    -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](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf), you wouldn't have seen any mention of a "stack" connected to operator `new`. – stakx - no longer contributing Aug 07 '11 at 11:31
  • @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. – Alexandre C. Aug 07 '11 at 11:47
  • 1
    @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. – stakx - no longer contributing Aug 07 '11 at 11:56
8

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"!

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
  • 4
    Please suggest this to the interviewers that are asking me heap vs stack questions in C# :) – Alex Aug 07 '11 at 11:16
3

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
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    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. – Kerrek SB Aug 07 '11 at 10:48
  • @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#. – Alexandre C. Aug 07 '11 at 10:51
  • 3
    Relevant articles from [Eric Lippert's blog](http://blogs.msdn.com/b/ericlippert/): *The Stack Is An Implementation Detail*, *[Part 1](http://blogs.msdn.com/b/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx)* and *[Part 2](http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx)*. – stakx - no longer contributing Aug 07 '11 at 10:53
  • 1
    @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...) – Kerrek SB Aug 07 '11 at 10:58
  • 2
    @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. – stakx - no longer contributing Aug 07 '11 at 10:58
  • @stakx: thanks for the links. However, as Kerrek points out, this is something they shouldn't worry too much about. – Alexandre C. Aug 07 '11 at 11:03
  • @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!) – Kerrek SB Aug 07 '11 at 11:08
2

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

Community
  • 1
  • 1
Dhruv Gairola
  • 9,102
  • 5
  • 39
  • 43
  • I was aware that Integer is a reference type and int is the primitive, but thank you for helping. – Alex Aug 07 '11 at 10:29
  • I don't know about c#, but in Java 6, something like int myInt = new int() will not compile. – Dhruv Gairola Aug 07 '11 at 10:37
  • 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. – configurator Aug 07 '11 at 10:38
  • In c# primitives can very much live on the heap - I've covered the scenarios in my answer – Marc Gravell Aug 07 '11 at 10:39
  • Oh! Iterator blocks. They hoist all their locals into the heap as well. – configurator Aug 07 '11 at 10:39
  • @configuration iterator blocks, boxes, arrays. – Marc Gravell Aug 07 '11 at 10:40
2

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.

However, you cannot instruct the runtime to allocate an object on heap or on stack. It's done automatically.

Bruno Reis
  • 37,201
  • 11
  • 119
  • 156
  • 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. – Arjan Tijms Aug 07 '11 at 12:29
2

Regarding c#, read The Truth About Value Types. You will see that value types can go on the heap as well.

And at this question is suggested that reference types could go on the stack. (but it does not happen at the moment)

Community
  • 1
  • 1
wimh
  • 15,072
  • 6
  • 47
  • 98
0

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.

Jagannath
  • 3,995
  • 26
  • 30
0

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.

See What uses are there for "placement new"?

Community
  • 1
  • 1
Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
  • 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. – Kerrek SB Aug 07 '11 at 21:11