19: C++ Destructors. Simply Reliable.
Take Up Code - A podcast by Take Up Code: build your own computer games, apps, and robotics with podcasts and live classes
Categories:
One of the biggest differences between C++ and C# is in how object lifetimes are managed. I was going to have a general topic on destructors just like constructors but there are just too many differences. So today, we’re going to look at C++ destructors. A destructor is just a method that belongs to a class or struct that gets called by the compiler at a specific time when an instance of your class goes out of scope. It gives you the ability to clean up or put things back the way you found them. It’s the last method your instance will run. There are two main uses of destructors in C++, to free memory that was allocated, and to release other resources such as file handles. You also learn some of the philosophy that guides how C++ decides what order to perform things such as calling destructors. This is important when multiple destructors all need to be called. Listen to the full episode or read the full transcript below. Transcript The first thing to understand is what does it mean to destruct an object and why is this necessary. If all you had to work with are just a bunch of ints, chars, bools, etc. sitting on the stack, then you wouldn’t need to worry about object lifetimes or destructors. This is because all the local variables get cleaned up when the stack pointer is adjusted back to its position before a method was called. Sometimes this is not enough. Let’s say you open a data file on your computer and have a local variable that keeps a handle to the open file. A handle is just some value in memory that the operating system uses to identify which file is open. The operating system will keep this file open until you close it or until your application exits. This means that when you’re done with a file, you should close it. If you don’t, then the operating system will think you still need it and this could cause problems later. Just letting the handle memory be reclaimed won’t actually close the file. You have to take this step yourself. Think of it like this. You’re at home when the phone rings. You answer the phone and start talking. At some point, you’re done talking and you hang up the phone. But what if you don’t hang up the phone? The call will end soon after the other person hangs up. But your phone line will stay open and other calls will get a busy signal. Answering the phone is just like opening a file. And hanging up is just like closing a file when you’re done. If you just stop talking and put the phone on the table, then that’s almost exactly what happens when you stop using a file and let the file handle be reclaimed without closing it. You need to sometimes take action to clean up things. This could mean calling other methods to close handles or freeing memory. We haven’t talked about memory allocation yet beyond just what you get with the stack. Now seems like a good time. Sometimes, you need a lot of memory. Either a big chunk for a single purpose or many smaller chunks that all need to be next to one another. The stack is a poor place to rely on large amounts of memory. You can get much more by asking the operating system for whatever you need. Of course the operating system has to have the memory you are asking for available or it can’t fulfill your request. Let’s say you ask for a million bytes of memory. With modern computers, you’ll probably get it. But here’s the thing. You might have a lot of memory, but it’s not unlimited. When you’re done with that million bytes, you need to return the memory to the operating system which will then add it back to the available pool of memory. You need to take action to free the memory. Just letting your variable that tracks your million bytes be reclaimed will only cause your program to forget all about the million bytes. But the operating system won’t forget. It will keep that memory dedicated to your program even if your program has completely