Modern C++ provides automatic memory management through vectors (dynamic arrays) and unique pointers (smart pointers that enforce exclusive ownership), eliminating manual memory allocation and preventing common memory bugs like leaks and dangling pointers. Vectors handle memory internally and resize automatically, while unique pointers ensure only one owner exists for each dynamically allocated object, automatically freeing memory when the pointer goes out of scope. Together, these features create code that is safer, more readable, and more maintainable than traditional C++ approaches.
Modern C++ Memory Management: Smart Pointers and Vector Containers
Added:today we're going to dabble in what I like to call introductory Advanced C++ by which I mean the simplest parts of modern C++ that you absolutely need to know if you're going to be working in the language all right here today in Dave's [Music] Garage hey I'm Dave welcome to my shop today we're going to look at some of the most fundamental aspects of modern C++ I think there are really two pieces you need to know in order to produce modern safe and effective code those pieces are the vector and the unique pointer why those two well it seems there's been a bit of a rush to learn rust of late as though it were the only solution for the problem of a bad C++ code you see most people and I was no exception when I got started write bad C++ code that's because they generally ignore what looks like a really complicated standard Library most new C++ programmers wind up writing what I like to call see with classes they break their code up into compartmentalized class classes and perhaps they use inheritance and polymorphism but that's only one aspect of C++ what winds up happening then is that they bring all of their bad C habits with them and they just wrap them into classes if you are still calling Malik or new or using simple pointers then you're one of the folks I'm talking about and I'll show you everything you need to know to stop doing it today you see rust protects you from yourself in most cases by simply prohibiting you from doing stupid things like having dangling pointers or using memory after it's been been freed common off by one errors and so on but you don't need to run out and learn a new language just to solve these issues because the modern C++ standard Library provides you everything you need to write code that has essentially the same protections but still in C++ and so there are a few things we won't be doing today we'll never allocate and free our own memory as that's the source of numerous defects in code and it makes your code patently unsafe so how do you write safe code in C++ and how do the allocations actually happen well it's all based around the notion of two pointer types provided by the standard Library the unique pointer and the shared pointer and because most nontrivial code needs to at least make use of arrays will introduce the vector class as well now I blame the naming of c++'s array class as the vector for turning off more new C++ programmers than any other Factor if I told you that C++ has awesome Dynamic arrays that grow and Shrink on demand and had all everything magically and that was called the array class you'd likely be down with that but as soon as you dip into a source or header file and see a bunch of vectors maybe you start thinking Matrix math and linear algebra and like a lot of people you run in the other direction so let's get it out in the open the array class in C++ is called vector and it's really just a dynamic array I suppose they could have called at the endle to make it even worse but either way correct or not Vector is just an array so when you see Vector think array using modern C++ features like vector and unique pointer can help create more correct code and reduce memory problems as a provide better memory management increased safety and improved performance these features simplify resource management and make the code more readable robust and maintainable the next complication that throws people for a loop part in the pun is the use of name spaces C++ packages its standard Library up into a namespace called predictably STD for standard and that means your code becomes full of standard colon colon vector and standard colon colon string and it can get a little unwieldly in verbose that's why today we're going to do something that I don't actually encourage you to do in the long run which is to add using namespace STD at the top of your source file just after the main includes doing so will allow you to just say vector or string or unique pointer without the STD prefix and the code becomes a lot simpler to read so for today we're going to run the risk of namespace collisions and ambiguity in favor of simpler code we're going to say explicitly at the top of our file that we're working in the STD namespace which allows us to refer to any in the standard Library without worrying about it being in a different namespace because our code will live in the very same namespace let's take a brief look at each component and then we'll dive into the editor and we'll explore them in a few examples vector vector is a dynamic array provided by the C++ standard Library it manages memory internally allowing growing and shrinking as needed whenever you add or remove elements this alleviates the need for manual memory allocation and deallocation reducing in the risk of memory leaks and other related issues using a vector has several advantages automatic memory management it handles all memory allocation and deallocation preventing memory leaks and ensuring that the allocated memory is released when the vector goes out of scope you never allocate or free objects directly you let the vector do it for you bounce checking the vector provides an at function that provides bounce checking helping you to prevent buffer overflow and other outof bounds access airs I rarely ever call it because I think actually having to call at to potentially throw an exception and find out whether your element is in the array or not uh it's a bit sketchy for me so I tend not to do it iterator support the vector supports iterators which makes it easier to work with the standard Library algorithms and range based for Loops you can create a for Loop that just iterates over every element in a vector without worrying about indexes and Bounds Dynamic resizing the vector grow and shrinks as elements are added or removed without the need for manual sizing now let's take a quick look at unique pointer unique pointer is a smart pointer provided by the C++ standard library that represents unique ownership of a dynamically allocated object it automatically deletes the object when the unique pointer itself goes out of scope using unique pointer has several advantages ownership semantics it enforces a clear ownership policy ensuring that there is only one owner of the allocated memory at any given time this avoids issues such as double deletion memory leaks and dangling pointers automatic memory management it handles memory allocation and deallocation automatically releasing the object memory when the unique pointer goes out of scope or is explicitly reset custom deleters it supports custom deleters which allows for more fine grain control over how the managed object is deleted for example in the esp32 code I write I have a special allocator just for external psram I don't manually allocate and free that psram I just specify that the relevant classes should use the psram allocator and the rest just happens automatically move semantics it supports move semantics which allows for the efficient transfer of ownership without copying the managed object this leads to much more efficient code let's take a look at some code I've written the very basic logic for a game of blackjack it just includes the logic for managing the deck the cards within it and the player's hand hands we'll start in the program's main function so we can see the overall logic before we delve into how it's all implemented I hope you'll agree that it reads quite straightforward first it declares a deck of cards then it calls Shuffle on that deck next we declare two player objects one for the player and one for the dealer then the player is dealt two cards Each of which is retrieved from the deck by calling draw a card we then repeat that process for the dealer so that both the player and the dealer each have two cards now I haven't included Logic for actually playing the hands out as I'm trying to keep it brief and clear so we simply display the two Hand values on the console to make sure that everything is working as expected with the player and the deck classes as that's where the substance of this code lives let's scroll up and look at those classes now at the top of the file we can see the ranks or the values of the various cards being defined in the rank enumeration each card has a simple English name and will have a value equal to what you'd expect for a card with that name next we Define the suits hearts diamonds clubs and Spades they're also assigned integer values but we never know or care what they are the card class represents a single card whether it's still in the deck or in the hands of the player or the dealer you create a new card by invoking its Constructor which requires that you specify the rank and the suit of the card internally each card tracks its Rank and suit and that's all it knows about itself the deck function is where we start to see some of the interesting memory management and modern C++ function ity one unfortunate part of C++ is that it doesn't provide a way to get the lowest and highest values in an enumeration so if you want to walk in an enumeration with a for loop it's up to you to know where to start and where to end for cards it's fairly simple we start with the ace that has a nominal value of one and work our way up to the King which is 13 in the index but for the suits we have to know that our enumeration starts with hearts and ends with Spades in any case we're going to create each of the 52 possible cards and add them to the deck but we're not going to create cards we're going to create unique pointers that own cards and let the pointers worry about everything else at the bottom of the class we can see that the deck's Vector actually holds unique pointers to card objects those cards can be as big and complicated as we want but we just hold pointers to them when the deck goes out of scope the vector will be cleaned up automatically and that means everything in the vector array will also be cleaned up as well if they were regular r c pointers we'd have to free the cards or some other similar nonsense but for a unique pointer the compiler knows authoritatively that the pointer owns the object that it points to and so it cleans up the cards as well remember that the vector is fully Dynamic it starts empty and we add cards to it and when it goes away it cleans everything up there's never any need to specify up front or later at any time how many objects your vector can or will contain you can optimize your code by doing so in some cases when you know what the sizes will be but it's not required you can just keep adding objects to a as often as you'd like and then remove them anytime you need and all of the memory management is handled for you there's no chance that you'll leak memory or reference elements that are no longer in the array or any of the common C pitfalls that have made C and C++ somewhat notorious for their lack of reliability when poor memory management techniques are employed back up where we do push the card into the vector you'll see that we're not creating a local stack version of the card and then copying it into the deck instead we're using a function called make unique that constructs a card dynamically and then returns a unique pointer to that card any objects to the card Constructor go right after to make unique call as normal now as noted a unique pointer is unique and that it is the sole owner of whatever it points to if a unique pointer goes out of scope or is otherwise destroyed then the object was tracking is automatically freed the pointer is inextricably tied to the card so it's almost as if the pointer is the card for our purposes but what if you copied the pointer well the thing is you can't duplicate a unique pointer and you can't have multiple pointer references to whatever it points to there's one and only one unique pointer per object all 52 cards then begin life as unique pointers to cards that are stored in the cards Vector in practice this means that you have a deck object in your main function the deck object owns the vector of cards and the vector of cards owns the unique pointers when the deck goes out of scope at the end of main the vector is automatically cleaned up and that in turn destroys each of the unique pointers that own the cards the unique pointers free the memory associated with the object pointed to automatically it's all about ownership and scope and doing it this way eliminates the numerous ways that you can corrupt or leak memory in standard C the deck class provides only two member functions Shuffle deck and draw card shuffle deck needs some way of generating random sequences and it's going to use the mt19937 engine to do it oddly named but this is very much like your good old C Rand function but it's a much better pseudo random number generator in fact the period or the number of cards it can generate before a cycle repeats is 2 raised to 1 19937 hence the name which is way more than the number of electrons in the universe so you should be good for a while the Syntax for the shuffle call which is part of the standard library is to give it the first and last cards in the sequence and then a reference to your random number engine and it does the rest for you when the shuffle call Returns the contents of the vector will be completely randomized it's worth noting that a unique pointer like a regular pointer can still be null which just means it doesn't own anything there's no object to free nothing to be done when it goes out of scope we see this in the draw card function when there are no cards left in the deck the deck will report that it's empty here and a no pointer will be returned now this doesn't mean that you have to constantly check your unique pointers for no before you use them it just means that when a function creates a unique pointer and fails it can return a null all you have to do is check for null before you add it to your array or collection in your air checking and you'll be safe if there are still cards in the deck we get the unique pointer out of the array by using move semantics move semantics warrant an entire episode on their own but it does essentially what you think it does since you can't make a copy of unique pointer even if you wanted to this call moves ownership from one place to the other from our deck to our local unique pointer which we will return to the caller the array still holds the now empty pointer so we call Pop back to remove it rest assured that even if we somehow forgot to call Pop back there's no room here for memory duplication or leaks just an empty card slot in the array you'd have a a logic bug to fix but it wouldn't corrupt leak or do anything bad with memory that's way easier to debug than Heap corruption next we move on to the player class down at the bottom we can see that the player has its own array of cards which represent the cards held by the player again this is a vector of unique pointers we don't have copies of the cards from the deck but rather our Vector will take ownership of whatever card is passed in through ad card note again that the card is never duplicated it is moved directly to the end of the array using again move semantics by never duplicating any cards we avoid all the possible pitfalls of trying to do that properly and every card that was ever in the deck is still either in the deck itself or in one of the player's hands the getand value function is largely uninteresting it just calculates the total value of the player's Blackjack hand and takes into account the weird scoring of the ace which can be both one and 11 depending on the other cards in your hand it also serves to make all of the face cards worth 10 as is the rule in blackj deck now that we've seen the deck in card classes let's return to main to have another look at how it actually uses them first as we can see our deck is shuffled it now contains all 52 cards in random order two cards are moved into the player's hand and two cards are moved into the Dealer's hand if we inspected the various vectors at this point we'd see that the deck now contains 48 card pointers the player's hand has two of them and the dealer has the other two every card is accounted for somewhere the code then prints out the value of both pans and that's it I hope it's a little more clear now how by using the vector unique pointer classes that you can create code that is effectively impervious to memory management bugs even logic bugs that will inevitably get introduced along the way won't cause crashes corruption or other common CA issues you just fix the logic and the code itself remains solid if you've enjoyed this episode and like to focus on coding please let me know by doing three things first make sure you're subscribed to the channel so I know that there's an audience for this stuff second if you assume that you already were subscribed this somehow people are getting unsubscribed periodically so click the blue arrow in the corner there to double check and third do take a moment to turn on personal recommendations if you want to see the episodes from this channel so that you actually find out when I do release a new episode being a smaller channel it's quite possible to just slip by without your notice I've put the code for today's episode up on GitHub and I'll include a link to it in the video description in the meantime and in between time I'll see you next time right here in Dave's Garage this little chair will be waiting for one of you and a rocking chair for another who likes to rock and a big armchair for two more to curl up in all next time on Dave's Garage [Music]
Up Next

Binary Search Tree Data Structure Explained | BST Operations
@mycodeschool
1.4M views•2014-01-25

BitTorrent Protocol Explained: Piece Selection & Peer Choking
@StevenGordonAU
481 views•2013-02-22

HTTP Requests Explained: GET, POST, PUT, DELETE
@codecademy
103.1K views•2021-10-07

Enigma Machine Mechanics: WWII Encryption Explained
@JaredOwen
13.2M views•2021-12-11
Related Study Plans & Knowledge Roadmaps
Structured learning paths in Computer Science
















![Dive into C++11 - [4] - Smart pointers](https://i.ytimg.com/vi/zMdD-s5_BIY/maxresdefault.jpg)

















