Multidimensional Arrays in C++ (2D arrays)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up guys my name is eternal welcome back to my C++ series so today we're gonna be talking all about multi-dimensional arrays in C++ 2d arrays three arrays 40 erase doesn't matter how many dimensions we have I'm just calling the multi-dimensional arrays because you can have as many dimensions as you want first of all if you haven't seen my video on arrays definitely check that out because I don't want to waste time explaining what an array actually is we're just specifically going to focus on multi-dimensional arrays and also definitely check out my video on pointers if you haven't already pointers are really important when you're doing with arrays of any kind because arrays are just blobs of memory and really is a way for us to deal with memory is by using pointers so definitely check it out okay so multi-dimensional arrays how they differ from regular arrays and why do we have them why don't we use them why maybe shouldn't we use them sometimes so multi-dimensional arrays we'll start with a 2d array two-dimensional array as an example really all it is is just an array of arrays and then if you have a 3d array it's an array of array of arrays right so a two-dimensional array is an array of arrays what I mean by that is it's literally a collection of arrays so if we think about one one of our kind of strategies for dealing with arrays is essentially by using a pointer so we have a pointer to the beginning of the array as it appears in our memory that's how we kind of that's how we deal with an array in this case right so if you picture that and then you picture an array of those pointers what you kind of end up with is I have a bunch I have a buffer in my memory which contains consecutive kind of pointers and each one of those pointers points to a array some way in my memory so we went on with is a collection of pointers to erase an array of a race right and we're gonna jump into some civil spots go to actually take a look at this because it can be a lot easier than trying to visualize it but that's basically what you end up with so if I come over here into my card what I'm going to do is just hip allocate a simple array to begin with just so that we're all on the same page let's just say I allocate 50 integers over here I'm just using a cape allocation for now with this is going to be easy to explain because we got a point on straight away and it's just a bit more power and what this actually is if I want to have a two dimensional array what I'm going to do is have a pointer of pointers because what I'm actually storing here is going to be a buffer of pointer objects right so this is a pointer to a collection of int pointers this is where it gets a little bit tricky because the allocation of two-dimensional arrays in C++ is some it's not really that straightforward in other languages like C sharp or Java you can just kind of it will just it'll allocate all the memory that it needs true for you and it's really easy to deal with with say plus plus is not because notice here what we've actually done we've changed from just having a pointer to an integer to having a pointer to a pointer to an integer so we've got a pointer to an integer pointer now not to an actual integer that's really really important because in this case we're building a 32-bit application so what we actually end up with is a pointer and integer being the same size but if we had an actual like class or a struct or something that was 20 bytes large for example then in the first case what we're actually doing is we're allocating 50 20 byte chunks right which essentially ends up with us having a thousand bytes of allocated memory whereas here what we're doing is we're allocating 50 pointers so 50 times force is 200 bytes of memory it's a completely different allocation size and if you actually look at this code and I'll kind of I'll say I can't call to the array I'll just call it a 2d array to do terrible naming I know what we're actually doing here is we're allocating 50 integer pointers so room for us to store 50 integer pointers that's all this is the actual arrays that we're storing haven't actually been allocated yet what we've just created here is we've essentially allocated 200 bytes of memory when you look at code like this it's really important for you to kind of think about what you're actually do you're not in any way creating integers whatsoever what you're doing is you're basically just allocating memory and all this this whole system of int and 50 that is just setting the size of the allocation we know that an integer is 4 bytes and we know that we want 50 of them so 50 times 4 is 200 so we're allocating 200 bytes of memory that is all this happening here nothing nothing's being initialized nothing's saying that Arkady's are integers doesn't matter I could then proceed to use this integer to store floats right all this array to store floats it doesn't matter what I've done what all that I've done is I've allocated 200 bytes of memory that's it right so the big thing here then if you look at this is that these these applications are actually identical what I've done here is the same as what I've done here okay all I've done is I've allocated 200 bytes of memory in both cases it's just that when I start to deal with these for example I say a 2d 0 equals whatever it may call that's a different operation right because if I address it like this I'm talking about an integer whereas if I address it like this I'm talking about it matches your pointer because that's the underlying type so that's kind of step one to this whole process and that's kind of my way of teaching C++ I need you to realize what's actually happening behind the scenes because that's the only way you're going to get good at using this language is by knowing what's happening so that you can then kind of play around with that and change that so the big thing here is again the type is just setting basically the syntax that you can use to deal with this data in the end it's 200 bytes that's all that you dunk this stage so what we want to achieve with our two-dimensional array can assist in here is now that we have room to store 200 bytes worth of pointers so 50 pointers we can then go through and set each of those pointers to point to an array and that way what we actually end up with is 50 arrays right so we have an array of arrays we have we have an array which contains the memory locations of 50 arrays hopefully that makes sense so if we go back here the way that we do this is we loop through 50 times through this a 2d array so we know that we have 50 of them and then we say a 2d at I equals new int 50 okay just like that so what that's done let's get rid of that single dimensional array here what we've done here is we've essentially allocated 50 arrays and each one of those arrays the location of each one of those arrays is stored inside this a 2d array and that is what a two-dimensional array is now if you had a three-dimensional array you have a nested followed so you'd go through and you'd allocate you have to allocate essentially you know the inner level which is kind of one dimension again it might be easier to just picture like a cube or something or a grid kind of cute' grid right and then just kind of go through and picture filling up each cell like you have to go through X through Y and through Zed there'd be three dimensions to that it'd be the same he might actually just be easier for me to show you so a three dimensional array would look like this we have a triple pointer here we'd be allocating a pointer of pointers then what we would what we would do here is we know that we have 50 pointers to pointers okay so this is getting a bit more confusing so what we have to do here is actually say I'll call this a 3d we'd have to say a 3d at index I and I'll actually change these to be probably x and y maybe all I and J will work as well so a 3d eye which is a pointer by the way that's the point two pointers would be equal to a new int pointer allocation of 50 right so we know how 50 of those and then for each of these we also want to go through them so upholds verbal J and allocate each of these so a 3d eye our maze the same and then this becomes J equals Neary and 50 okay so we've added another index here because and I'll break this down a little bit so it's more easier to see because this a 3d is appointed to a pointer to a pointer so this is kind of dereferencing the first part of that pointer and then this is to referencing the second part of that pointer so it'll be the same as if I said let's get our a 2d from this or our 2d kind of point in here so we'll say PC R equals a 3d I right and then to this a 3d I I'm going into oh sorry to this point Oh what am I saying answered ad which is pointer I'm actually saying access that at index J and set that up with 50 of those so this is a 3d 3d allocation okay what we're doing here is we've got 51 quote 50 I'm like confusing myself by saying this I hope this is making sense this is one of those cases where you're gonna have to sit down stare at this code maybe draw something on a piece of paper and figure out how it works because this is pretty difficult to explain I'm not gonna lie back to this there I'll give it one more shot so again what we have here is three pointers okay well not three pointers but a pointer to a pointer to a pointer that's our type we've created what we've done here is we've allocated 50 pointers I might actually make a video on what point is the point is mean because that might be confusing in itself anyway we've allocated 50 pointers to pointers right we're going through each of those pointers to pointers and creating an array of pointers and then we're going through each of those pointers because what we have here is just normal array of pointers and we're setting each of those pointers to an actual array so we're allocating our actual type here int and this is what we would this is the actual type allocation because this is you know this is just a point around occasion like we're allocating an array of pointers here but here we're actually allocating our array of integers and then if we want to access this we'd have to go a 3d and then kind of you know the outer coordinate these middle coordinate so X Y and then we'll save that and then that's how we would set each one of those okay so you can see that it literally is a three dimensional array because if we just take that that's going to give us an array of pointers to pointers and if we take that it's going to give us an array of pointers and then this is what actually gives us our so hopefully that kind of makes sense anyway back to the 2d example that it's gonna be way easier to explain again 0 and then 0 this is the first element and if you want to go to the second element that's is like that the third element like that you have to remember that this row here is kind of the rightmost row that is your actual integer that you're accessing if you shift over and you take a look at this column here that is just that is the index of a pointer not of an integer because that's this array that you're actually dealing with that's what this column is whereas this column on the right here is actually this inner array that you're dealing with okay so that's two-dimensional arrays now when it comes to deleting them which is what we have to do as well if we keep allocate them like this you have to go through and iterate and delete all of those arrays because you can't you can't you can't just do it this if I go ahead and I say delete and I do a 2d or whatever like that sorry you can you'll note by the way I typed that there specifically you'll know that there is no such thing as that operator so you don't need to wait array like that if you go ahead and you just do that do that and you delete it what that's gonna do is that's going to release this memory which is just 200 bytes by the memory it's just the array that holds pointers to your actual integer arrays so all of those 50 times 200 bytes that you have there that is your actual data there's all those 50 arrays they're now gonna be a memory leak because we have no way to access them we can't delete them in the future cuz we just deleted the array that held those pointers that told us where those other arrays were so what you actually have to do to delete this is iterate through this 50 times and delete a 2d at index I like that that is what deletes it and then finally you also have to delete a 2d so that's kind of the reverse of that all right hopefully that made at least a bit of sense if you have questions please leave them in the comments below and I I'm sure I'll end up making videos this was a hotter video to make and I'm not a cleat done yes I'm gonna keep talking for a bit what I've what I've said here is that an array a two-dimensional array or multi-dimensional arrays is an array of arrays now here's my issue with this whole thing apart from evidently being really hard to deal with it's the fact that when you're dealing with an array of arrays you result in it that dis results in memory fragmentation so what I want here really and let's just again I'm just gonna I don't know why one with 50 let's go with 5 that's a bit of a more of a magical example to deal with because we can actually picture 25 elements if we have an a what we have here is an array of 5 arrays and each one of those 5 arrays is an array of 5 integers so we have 25 integers 5 times 5 is 25 okay each instead of us having just one continuous buffer that was capable holding 25 integers just in a ROM in memory what we've actually done is we've created five separate buffers of five integers each okay they're gonna be allocated unless you're using some kind of custom allocated order or an arena or something like that they're gonna be allocated and completely random places in memory they might be close together there there might not be nothing guarantees they're gonna be close together that's an issue because if we have to iterate through an access agent those 25 integers every time we iterate through five integers and we go to the next row of our array or our next dimension basically we drop down to our next integer array we have to jump to another location in memory to read to access that data to read or write that data and that's the results probably in a cache miss which means that we're wasting time fetching that from our actual RAM it might not be a cache miss if they happen to be allocated close together but again there's nothing for us to we can't rely on them being allocated close together they're most likely not going to be so because of that it's actually going to be slower a lot slower a lot slower to iterate through these 25 integers this way then if I had just allocated a single dimensional array of 25 integers in a row in memory because that memory is going to be all in a row and one of the most important things when you're programming and you're optimizing and you're dealing with memory well one of the most important things you can do to optimize is actually optimize your memory accessing so if you can store memory close together that you'll be accessing and you can kind of actually position it in a way that results in more cache hits and less cache misses your program will perform faster and we're definitely going to learn more about caching and health of CPU cache works and all that in the future this is kind of a good way I think to introduce it now people say well I need a two dimensional array there's no other way to deal with it right wrong you've got 25 integers here that's what you've made you've made an array of 5 integers 5 times that's 25 integers can you really not think of a better way to store 25 integers you can just store them in a single dimensional array look I'll show you what you can do here is just make an array of 5 times 5 integers okay okay so let's just say I want to set all these integers - I don't know - so I'd have to iterate through them this way we'll say for in form y equals 0 Y is less than 5 y plus + and then we'll have to so that iterates through our array of pointers and then we'll go in the inner loop changes to X and we'll get array through the actual arrays and we'll say a 2d XY equals - ok that's how I set it you know like this is cool though because it's like I've got a 2d grid and I can be like oh yeah index you know X is 2 y is 3 like it's really easy to deal with like that well you can do the same thing here I mean obviously if you wanted to set everything to 2 in this array all you really would have to do is just say for n I 0 is less than 25 or 5 times 5 I plus plus and then array I equals - easy mr. easy right but you could also write it this way and then it's just instead of doing that you just say X plus y times the width of your array which is five so this kind of dimension over here right or this dimension it doesn't really matter what doesn't matter because it's your width if you have a grid this is your width because what you're saying here is you're saying that every time the Y increments I want you to jump five elements forward which would be the equivalent I'm just dropping down a row if you had your grid okay we can talk about this in more detail if you would like leave a comment below I'll see what kind of what your thoughts are it's hard for me to gauge where you guys are at this point like you are like I mean I know that obviously a lot of people with very varying kind of skill sets watch these videos but now that you know that there's like 50 plus of these videos I feel like you guys are kind of like my class on my students and I really want to know where you're at so if you don't understand this stuff and you want me to explain it with diagrams in a bit more a bit more then I'll definitely do that anyway so that's kind of the idea here you can see that I can access this exactly the same way as a two-dimensional array but guess what this code is actually a lot faster than this code because this code every five every time we go to this outer for loop has to jump to a completely different array in memory or if this is just accessing that same memory that's all in a row in our actual memory so I personally avoid 2d arrays as much as possible sometimes it makes a lot of sense to use them unless the time it doesn't okay if I was storing a bitmap for example and I had all the pixels in an image you might think of an image like a photo like a texture as a 2d thing right like you've got pixels and it's like a - it is like a 2d grid right so I should store it as a 2d array right no store it is a single dimensional array it doesn't matter that you can't like you can still it doesn't matter how you story you can start as a two-dimensional array or a one-dimensional array but the one-dimensional right way is gonna be the much much much more optimal way of actually storing that image anyway I hope you guys enjoyed watching this video if you didn't hit the like button you can also help support the series by going a patriotic involves laughter the cherry huge thank you to all the patrons that make this series possible because it wouldn't be here without you if you want the plenty of critical rewards for supporting the series such as getting like a monthly hang out with all the other supporters of that tier as well as source code access to my opengl series and like a private discord like channel where we can talk about stuff and there's plenty of stuff there and it really does help support the series so thank you so much those people yeah I'm really interested with this video to see what you guys think so leave a comment below and I'll see you in the next video goodbye [Music]
Info
Channel: The Cherno
Views: 114,425
Rating: 4.915236 out of 5
Keywords: thecherno, thechernoproject, cherno, c++, programming, gamedev, game development, learn c++, c++ tutorial, 2d array, multidimensional arrays
Id: gNgUMA_Ur0U
Channel Id: undefined
Length: 20min 20sec (1220 seconds)
Published: Mon Apr 09 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.