14

From what I understand, in standard C++ whenever you use the new operator you must also use the delete operator at some point to prevent memory leaks. This is because there is no garbage collection in C++. In .NET garbage collection is automatic so there is no need to worry about memory management. Is my understanding correct? Thanks.

Wim
  • 11,091
  • 41
  • 58
Brandon Tiqui
  • 1,429
  • 3
  • 17
  • 35
  • 9
    One hundred percent correct! – henle Nov 08 '09 at 01:33
  • 11
    99.9% correct. There are cases where you need to worry about memory management in .NET. – jmucchiello Nov 08 '09 at 01:43
  • 1
    in C++/CLI you allocate using 'gcnew' however you can still use 'new' but they then needs to be paired with 'delete', just like in fully unmanaged code. – AndersK Nov 08 '09 at 01:49
  • Almost right. Sometimes you have to dispose resources explicitly without waiting for GC to do it for you. –  Nov 08 '09 at 02:05
  • The title is misleading, you may want to change it (did you mean in .NET instead of C++?) – JRL Nov 09 '09 at 16:00

8 Answers8

20

The long answer to it is that for every time new is called, somewhere, somehow, delete must be called, or some other deallocation function (depends on the memory allocator etc.)

But you don't need to be the one supplying the delete call:

  1. There is garbage collection for C++, in the form of the Hans-Boehm Garbage Collector. There is also probably other garbage collection libraries.
  2. You can use smart pointers, which use RAII (and reference counting if the pointer allows shared access) to determine when to delete the object. A good smart pointer library is Boost's smart pointer. Smart pointers in the vast majority of cases can replace raw pointers.
  3. Some application frameworks, like Qt, build object trees, such that there is a parent child relationship for the framework's heap allocated objects. As a result, all is needed is for a delete to be called on an object, and all its children will automatically be deleted as well.

If you don't want to use any of these techniques, to safeguard against memory leaks, you can try using a memory checking tool. Valgrind is particularly good, although it only works on Linux

As for .NET, yes, allocating using gcnew means that the memory is tracked by .NET, so no leaks. Other resources however, like file handles etc. are not managed by the GC.

blwy10
  • 4,862
  • 2
  • 24
  • 23
  • 6
    One of the advantages(!) of RAII is that you can manage resources other than memory, e.g. file handles. Delete the object, and voila the file owned by the object is closed, too. – casualcoder Nov 08 '09 at 03:04
  • Don't forget about SBRM while we're throwing around acronyms. fstream for example will automatically close its file when it goes out of scope. Also remember that member variables have a scope of the life of the parent object, which makes SBRM very convenient even without a destructor. – joshperry Nov 08 '09 at 03:18
  • 1
    I think the SBRM you refer to for fstream is RAII. – blwy10 Nov 08 '09 at 03:33
  • 1
    @joshperry. There is always a destructor (though it may be compiler generated) – Martin York Nov 08 '09 at 04:08
10

In idiomatic high-level C++, you never call delete.

C++ does not have a standard garbage collector that works the same as in C#, and therefore it is true that fundamentally, new and delete need to be paired. However, there are mechanisms in C++ that completely eliminate the explicit use of delete for code written in the modern style.

The first thing to note is that in C++ you use new much less frequently than you use new in C#. This is because in C# you use new whenever you create an instance of a structure, class, or array, but in C++, you use new only when you want to manage a data element dynamically. Most data in C++ does not require dynamic management and can therefore be created without the use of new. [Put another way, new has a different meaning in C# than in C++. In C++ it specifically indicates dynamic allocation, while in C# it is used for any construction.]

Secondly, any time you do call new in C++, the return value should be handed directly to a smart pointer. The smart pointer will ensure that delete is automatically called for you at the appropriate time.

By the way, unless you are a guru writing a low-level library (or a student learning how to do this), you should never call new to allocate an array in C++. The standard library (and also Boost/TR1) provide template classes that allocate and manage arrays for you.

In summary, C++ does not use a garbage collector but it does have its own form of automatic memory management. There are subtle differences between the two approaches, but both approaches automate the release of memory, thereby eliminating most types of memory leaks.

The authoritative demonstration of these concepts is given by C++ creator Bjarne Stroustrup in answer to the question: How do I deal with memory leaks?

See also:

Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173
  • By the same token, if you do use delete, it is probably a bug. The problem is that the use of delete assumes that you know exactly how the program's control flow will proceed so that the delete will occur at the appropriate time. This is an easy, but naive, assumption to make. First of all, it requires some measure of carefulness to properly position the delete operation. More importantly, exceptions can generally occur at any intermediate point in the code and violate your assumptions about control flow. Fixing this with try/catch is possible, but it is not a "best practice". – Brent Bradburn Nov 09 '09 at 16:10
  • 1
    Bjarne's demonstration is somewhat dated, particularly his use of auto_ptr<> which is typically shunned nowadays (there are better alternatives). But this demonstrates the maturity of what I previously called "the modern style". Bjarne has been teaching this approach for a long time. – Brent Bradburn Nov 09 '09 at 17:15
  • Here's a post that says about the same thing but elaborates more on the mechanics -- including discussion of some of the newer library features: http://stackoverflow.com/questions/4963610/visual-c-native-memory-management-best-practices/4963633#4963633 – Brent Bradburn Feb 11 '11 at 03:15
  • As noted in a comment [here](http://programmers.stackexchange.com/a/322447/18571), C++14 added `std::make_unique`, and this eliminates nearly every use of `new` as well. – Brent Bradburn Jun 17 '16 at 21:57
  • Nice video: [Writing modern C++ code: how C++ has evolved over the years](https://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-835T). – Brent Bradburn Jun 17 '16 at 21:57
  • Probably *subtle* is not the right way to describe the differences between C# and C++ memory management. In general, the similarities begin and end with -- you don't call `delete`. – Brent Bradburn Feb 20 '17 at 05:46
  • It might be fun if C++ deprecated `new` and replaced it with `dynamic`. This would be a bit more intuitive, I think. ... Perhaps excluding the rare "placement new" usage. – Brent Bradburn Apr 23 '17 at 15:36
8

Your statement about operator new is totally correct...but it's oversimplifying C++ semantics quite a bit.

In C++, objects can be created on the stack or on the heap:

class Foo {};

int main() {
  Foo obj1;
  Foo* obj2 = new Foo();
  delete obj2;
}

In the above example, obj1 is created on the stack and obj2 is created on the heap (with new). Objects created on the heap are not destroyed until delete is explicitly called on them. However, objects on the stack are automatically destroyed when they go out of scope (i.e. when main() returns in this example).

This enables the "Resource Acquisition Is Initialization" idiom (a.k.a. RAII) in C++, which is much more powerful than basic garbage collection. Resources that need to be cleaned up (heap memory, sockets, files, DB connections, etc.) are generally put in stack-based objects whose destructors take care of cleanup.

In contrast, Java and C# don't allow objects to be constructed on the stack, and do not guarantee that collection will ever happen nor that finalizers will run (I'm not a C# guy, so I may be a little wrong there). So while you get free heap memory management in Java/C#, you'll actually end up with a lot more resource cleanup code in those languages than you do in C++.

Drew Hall
  • 28,429
  • 12
  • 61
  • 81
2

Yes you are right, in standard C++ (In managed C++ or other variants it depends) you must use delete after each new. In C#, Java and other garbage-collected languages, this is not necessary (in fact most of them doesn't have an equivalent to the "delete" operator).

AntonioMO
  • 898
  • 1
  • 6
  • 16
1

"there is no garbage collection in C++."

Correct.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • 2
    Not true. There are Garbage collectors available. (And its not that hard to build your own). – Martin York Nov 08 '09 at 04:06
  • 1
    "available" or "a standard feature of the language?" The question is about standard features of the language. Not available. Smart Pointers (IMO) are essential, but not a standard feature of the language. – S.Lott Nov 08 '09 at 13:22
1

You can use C++ with .NET in two ways: managed or unmanaged. In managed mode, .NET's garbage collection will take care of freeing memory on your behalf; in unmanaged mode, you're close to C++'s normal/standard behavior, so you have to take charge of your memory yourself.

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 4
    Regardless of the "mode", every `new` is unmanaged memory and has to be deallocated manually by `delete`. C++/CLI adds `gcnew`, but this is not C++ as such, and rather a language extension. – Pavel Minaev Nov 08 '09 at 01:48
  • 3
    Really we are talking about two different languages. C++ and C++/CLI – Martin York Nov 08 '09 at 04:07
1

Automatic garbage collection is useful, but you can still get memory leaks, as this question shows:

Memory Leaks in C# WPF

It is decreased in .NET and Java, but that doesn't mean it allows bad coding to be taken care of automatically.

So, in C++ you need to explicitly release what you request, and I think that is sometimes better, as you are aware of what is going on. I wish in .NET and Java that the garbage collector did little in Debug mode, to help ensure people are aware of what they are doing.

Community
  • 1
  • 1
James Black
  • 41,583
  • 10
  • 86
  • 166
0

Correct you have to worry about garbage collection on C++.

And... there is no need to worry about garbage collection on .NET.

Only if you have such intensive and long scripts that you feel need the optimization do you need to focus on that.

Edit: Both asveikau and Pavel Minaev comments are great, thanks! I overgeneralized to pass the message.

Frankie
  • 24,627
  • 10
  • 79
  • 121
  • I wouldn't say completely that you "don't have to worry about it". For some types of objects, you _do_ need to be careful to perform manual cleanup, even in C#. For example, you should be sure to close files, and not rely on GC to do it for you. – asveikau Nov 08 '09 at 01:40
  • 1
    And, of course, nothing stops you from allocating unmanaged memory in C# (or other .NET language), which you then have to release yourself. See `Marshal.AllocHGlobal` etc. – Pavel Minaev Nov 08 '09 at 01:49