VECTOR/DYNAMIC ARRAY - Making DATA STRUCTURES in C++

แชร์
ฝัง
  • เผยแพร่เมื่อ 26 มิ.ย. 2024
  • The first 1000 people who click the link will get 2 free months of Skillshare Premium: skl.sh/thecherno0820
    Patreon ► / thecherno
    Instagram ► / thecherno
    Twitter ► / thecherno
    Discord ► thecherno.com/discord
    Series Playlist ► thecherno.com/cpp
    This video was sponsored by Skillshare.

ความคิดเห็น • 292

  • @TheCherno
    @TheCherno  3 ปีที่แล้ว +63

    Hope you all enjoyed the video! Have a go at the exercises and implementing some of the features we didn't get to in this video (eg. copy/move constructor + operators for the Vector class). And finally don't forget that the first 1000 people who click the link will get 2 free months of Skillshare Premium: skl.sh/thecherno0820

    • @khealer
      @khealer 3 ปีที่แล้ว +2

      You could branch on a if constexpr(std::is_pod::value) and if it is, just memcpy things, otherwise copy construct.

    • @algorythm4354
      @algorythm4354 3 ปีที่แล้ว

      I am really happy with this video! While you provided the solution, I wish you would have also highlighted the issue of the old allocation: it constructs! Imagine if your class had a Sleep in the constructor, or more realistically, a heap allocation. With out operator new, it would slow you down substantially whenever you wanted to resize your vector. Especially over thousands of items.

    • @vsevolodnedora7779
      @vsevolodnedora7779 2 ปีที่แล้ว

      Hello! Thank you for the video and for your work!
      I found that the... outcome of this code depends strongly on the compiler. May I humbly suggest a topic for a video about compilers in more details, which one do you use with what flags and what are the pitfalls or gcc, g++, clang, calng++.
      I am working in Ubuntu and I found that the only compiler that works for this project is "rustc" that I've never heard of before :)

  • @sumeetsuryawanshi8384
    @sumeetsuryawanshi8384 3 ปีที่แล้ว +173

    Bro please don't give up on finishing this series ...u r all I can rely on.🙏

    • @vitluk
      @vitluk 3 ปีที่แล้ว +3

      amen

    • @exodusfivesixfivesix8050
      @exodusfivesixfivesix8050 3 ปีที่แล้ว +2

      This is literally my first stop before reading text book.

  • @thestarinthesky_
    @thestarinthesky_ 3 ปีที่แล้ว +50

    Love this topic: Data Structures in C++ . Thank you soooo much .

  • @Goejii
    @Goejii 3 ปีที่แล้ว +52

    Recreating the vector class is a good exercise to explore and experiment various useful features of C++

  • @joa_joa
    @joa_joa 3 ปีที่แล้ว +13

    I'm really enjoying these longer C++ videos, keep it up ! and thanks !!

  • @tannerbarcelos6880
    @tannerbarcelos6880 3 ปีที่แล้ว +4

    Learning data structures in c++ makes it much easier to understand and do in other languages. C++ was the language used in my comp sci program for intro to computer sci and for data structures and algorithms and now I’m doing data structures and algorithms in JavaScript preparing for interviews and that foundation in c++ helps a ton.
    If anyone is a student and has to do c++ in school, don’t be overwhelmed. Trust the process, work hard, and you’ll do just find.
    Cherno clutch yet again with perfect quality content!

  • @PrinceGupta-jo8lo
    @PrinceGupta-jo8lo 3 ปีที่แล้ว +4

    The inplace new and operator new/delete part was new to me, and really amazing. I knew I'll learn something new from your video.

  • @supersquare
    @supersquare 3 ปีที่แล้ว +146

    Would love to see a video on variadic templates someday :)

    • @donrumata5299
      @donrumata5299 3 ปีที่แล้ว +14

      With forwarding references...

    • @donrumata5299
      @donrumata5299 3 ปีที่แล้ว +9

      Implementing an std::invoke clone

    • @treyquattro
      @treyquattro 3 ปีที่แล้ว +6

      I'm guessing you would live to regret it

    • @PixelThorn
      @PixelThorn 3 ปีที่แล้ว +3

      Urgh, that...

    • @enriquellerena4779
      @enriquellerena4779 ปีที่แล้ว

      We’re still waiting for his Exceptions vid he promised around 4 years ago 😂

  • @supersquare
    @supersquare 3 ปีที่แล้ว +5

    Thank you so much Cherno, this video is absolutely phenomenal

  • @krishp4907
    @krishp4907 2 ปีที่แล้ว +7

    Wow, that gotcha moment at the end was so inconspicuous that I'm a bit shaky in writing efficient C++ code and debugging it. May this series never end for the good of me!

  • @Nikiux133
    @Nikiux133 2 ปีที่แล้ว +57

    You still have a bug in ReAlloc function in line 95: newData[i] = std::move(...); - you can't use assignment operator here (either move or copy) because newData[i] is uninitialized memory - it is not the object of type T and by calling operator= (again move or not) you treat it as if it is object of type T. So instead of that you should use placement new once again so change that line to: new (&newData[i]) T(std::move(m_Data[i]));

    • @Serenity-cr1sw
      @Serenity-cr1sw 2 ปีที่แล้ว +7

      Thank you man!!!! I am looking for exactly the fix for this issue! The code does not work for std::string, it crashes exactly at this line!! Thank you man I appreciate it!

    • @triangl3boi
      @triangl3boi ปีที่แล้ว

      Yes, I've noticed that too. I'm mostly going by myself but my ReAllocate function is very similar to this. My constructor for a class allocates some memory but the constructor is not called so when assigning (copy is called) the data is just leftover memory.

    • @afterlife1578
      @afterlife1578 ปีที่แล้ว +2

      he has addressed this issue in the writing an iterator video

    • @darshanghorpade9590
      @darshanghorpade9590 ปีที่แล้ว

      hey newBlock is of type T* so I replaced the code you gave, but now its showing Buffer overrun while writing to 'newBlock' error 'Vector3::Vector3(const Vector3 &)': attempting to reference a deleted function

    • @AlexeiFarWest
      @AlexeiFarWest ปีที่แล้ว +2

      It is initialized. When you create your array as "new T[size]" it initializes every element with default constructor. Which is a problem, because what if your value_type doesn't have default constructor? To create uninitialized array you need to use allocator. I also would suggest to use std::construct_at instead of placement new operator. It does the same thing, but more descriptive and easier for an eye.

  • @cm0786
    @cm0786 3 ปีที่แล้ว +8

    About 2 years ago I really became intrigued by stl. The vector class was the first one I tried recreating. And failed miserable. How ever I have redone this exercise about 20 times since. And I can write a vector class with the majority of the features one would want in about 1 day. I encourage everyone to do this exercise every once in a while. You always learn somethimg new.

    • @leocarvalho8051
      @leocarvalho8051 3 ปีที่แล้ว

      I am planning on writing my own stl

  • @badwolf8112
    @badwolf8112 3 ปีที่แล้ว +1

    LOVE THIS SERIES. THANK YOU.

  • @crisdellani
    @crisdellani 3 ปีที่แล้ว +1

    After all the fame, the fact that you keep this C++ series for dummies like me going, is amazing! The game engine series is way over my head and the reaction videos are not really my thing.. but I do hope that you are getting all the compen$ation you want because you deserve it... kuddos mate

  • @koungmeng
    @koungmeng 2 ปีที่แล้ว +1

    Thanks, mate! I really learned a lot from making my own version of the STL vector.

  • @foomoo1088
    @foomoo1088 ปีที่แล้ว +1

    Very cool! I think I “know it all already” but usually learn something new in these! I’m writing my own containers now for my personal engine project and great to get some ideas from The Cherno 😀

    • @foomoo1088
      @foomoo1088 ปีที่แล้ว

      Also might need to check for “self” in your “moves”

  • @bassbatterer
    @bassbatterer 3 ปีที่แล้ว +2

    Funny you put this video up, Just today and yesterday i've been working on my own spin on this.

  • @youcefsb4708
    @youcefsb4708 3 ปีที่แล้ว +10

    For all those who did make it to 36:05, and then got lost after "HAHA did you think that was it?", Kudos to you.

    • @sandeepkalluri
      @sandeepkalluri 3 ปีที่แล้ว

      Somebody explain to me

    • @cavalfou
      @cavalfou 2 ปีที่แล้ว +5

      ​@@sandeepkalluri Essentially, delete operator does 2 things: call dtor, and then free memory. delete[] call dtor of each of its elements, then free memory. The problem is, if we manually call dtor of some item, it will in fact delete its members memory(int* in our Vector3 example), but the Vector3 instance is still physically present in the contiguous array of our Vector instance. That means that if we call the Vector delete[] method, ie when the Vector instance is out of scope in this case, Destructor of each item may be called Twice ! The problematic items here are the one cleared or popped back.
      When delete[] iterates through items to call dtor and free, it will not stop at our m_Size defined value, but out Clear implem does.
      If you want to check stuff by yourself, just simply emplace and immediatly pop some object from Vector in debug mode. You can clearly see that in the memory our object is still living after pop. Destructor of an instance manages its member destruction, not the object itself.
      We have a similar concern with the new operator(although it doesn't cause crashes): it allocate memory, then call ctor. In case of re allocating resource (or "reserving"), we want to make sure we have enough space for our future item to be added. We do not want to actually create default objects waiting to be overwritten by future actual pushed back ones.
      That is why we use this syntax:
      ::operator new
      which only allocate UNINITIALIZED memory, ie memory we own but may contain unpredictable garbage.
      Hope this helps.

    • @vintagewander
      @vintagewander 2 ปีที่แล้ว +1

      ​@@sandeepkalluri
      new calls the allocator to allocate memory, with size of the type you passed in, and then call the constructor to create an object on that memory allocated
      delete calls the destructor first, and then calls the deallocator to deallocate memory
      the ::operator new only allocates memory, and it does not construct anything, the memory is now yours, but it has nothing in it,
      to construct an object of type T in that memory, you have to do something called a placement new
      new(address) ctor(data)
      so the normal new operator that you would normally use, it does two things automatically, allocate, then construct
      in this video, what you're doing is you do those two things by your own
      the same goes with ::operator delete(ptr, size * sizeof(T))
      it only deallocates, and does NOT call the destructor
      so what the normal delete would do is to call destructor, then call the ::operator delete behind the scenes, the deallocate
      since in this video, you have a lot of parts that you call the destructor explicitly, and then finally you call the normal delete, which calls the destructor again, despite that it has already been called at some other part of the code
      if you're sure about calling the destructor exactly where and when you wanted, then all you need is the deallocator
      And since you can't call ::operator delete on the normal new, you have to also do the two task: allocate by using ::operator new and placement new manually, just so the ::operator delete can work, deallocates what ::operator new has allocated

  • @GeekyMino
    @GeekyMino 3 ปีที่แล้ว +1

    I really enjoy watching your videos! Keep up the good work!

  • @daniilmurray3751
    @daniilmurray3751 3 ปีที่แล้ว

    Hey Cherno! Thanks for the video, your content progresses every video and it looks amazing.
    It would be amazing if you made a video about custom memory allocators. I'm currently making my own engine and it appeared to be a very important topic. Although I've read several books on the topic, I never seen an example of an implementation with usage examples. That'd be a great topic!

  • @eeneemeenee6236
    @eeneemeenee6236 4 หลายเดือนก่อน

    I like the honesty about difficulty and serious attitude towards learning c++

  • @notpipa_
    @notpipa_ 3 ปีที่แล้ว +1

    Great video! Do you plan to do some algorithms like breadth first search in the future?

  • @PedroOliveira-sl6nw
    @PedroOliveira-sl6nw 3 ปีที่แล้ว +1

    I was halfway happy that I had done pretty much the same and then I realized he was going to implement a lot of the vector interface :D

  • @sascha9778
    @sascha9778 5 หลายเดือนก่อน

    Amazing course! Thank you a lot for this "demo"! 🙏

  • @stepanhrbek8151
    @stepanhrbek8151 3 ปีที่แล้ว

    Wow, that was AMAZING!

  • @appleuser4627
    @appleuser4627 3 ปีที่แล้ว

    Well done bro, full support from India.
    And thank you for amazing advanced tip.

  • @user-ei1vi
    @user-ei1vi 3 ปีที่แล้ว +22

    It will be great if you consider to modify your custom vector class to work with range-based "for" loop and show us how

    • @Beatsbasteln
      @Beatsbasteln 3 ปีที่แล้ว +5

      i think that's what he meant when he said he'll make a video on iterators

    • @user-ei1vi
      @user-ei1vi 3 ปีที่แล้ว +2

      Already figured out how. I have just write begin() and end() methods which returns something acts like iterator, but i done this in custom string class, in vector class it should work the same way.

  • @reedsdevine336
    @reedsdevine336 2 ปีที่แล้ว

    Since We're big boys here... 8:25
    It cheered up my dull day, thanx cherno

  • @justwatchingstuff1507
    @justwatchingstuff1507 2 ปีที่แล้ว

    I don't know if you read all your comments but I just wanted to say I really am liking you breaking things down!

  • @OneShot_cest_mieux
    @OneShot_cest_mieux 3 ปีที่แล้ว

    That was really helpfull, thank you

  • @riteshpathak6588
    @riteshpathak6588 3 ปีที่แล้ว

    Thanks man i was literally finding how to make ouch back function interally and also how to increase capacity if capacity is ful

  • @binary_gaming113
    @binary_gaming113 3 ปีที่แล้ว +3

    Thank you for the great video! Will you do a tutorial on custom allocators some day? There are not really that many tutorials on it.

    • @martian8817
      @martian8817 3 ปีที่แล้ว

      try implementing vector using the the specifications on cppreference, just by encountering custom allocators in a practical setting actually teaches you a whole lot about them (tip : look up std::allocator_traits first to see how c++17 and on handles allocators. )

  • @vunderstudios
    @vunderstudios 2 ปีที่แล้ว

    an optimization that i use in my game engine array class, is using type traits to check if T is a POD, and if so using memcpy (not memmove for performance) to copy elements instead of using std move. compilers may notice this, but i added it just in case

  • @wizzenberry
    @wizzenberry 3 ปีที่แล้ว

    My god this is amazing

  • @jesseburstrom5920
    @jesseburstrom5920 3 ปีที่แล้ว

    Wee it is warm here in Sweden now. I agree data structures are important. I realized type casting can be 'very bad' in Flutter. I call MySql get back array of Json objects, used an online example to get the socket io. Problem was just that casting to MAP is wrong since it only works in one dimension. So put var(VAR) let the structure be as it is. Never typecast if not absolutely necessary. Still a bit confounded with the place in development but it is all clear really. Next step is... the rest i just make it bit by bit as we say. Great video by the way!

  • @blazingazong
    @blazingazong ปีที่แล้ว

    Stack allocated vector that is actually just a single node in a linked list. Every so often you get a slower step, but I am so intrigued to try implementing it

  • @30saransh
    @30saransh 3 ปีที่แล้ว +4

    Please don't give up on this series. I started it yesterday and I am on video number 20. I love the way you teach.

  • @martian8817
    @martian8817 3 ปีที่แล้ว +3

    I really enjoy exercises like these (std::tuple having been my favorite so far) and what i do is to go to cppreference and copy over the function signatures to be implemented later. this forces you to encounter things like custom allocators (which greatly improved my ability to optimize my code in larger projects) and learn how versatile templates can be.
    In the case of vector i actually, rather than keeping track of sizes just kept track of a :
    struct { struct { pointer begin, end; } allocation, elements; } m_data;
    which has some time saving properties to it.

  • @VivekYadav-ds8oz
    @VivekYadav-ds8oz 3 ปีที่แล้ว +1

    This video inspired me to create a sort of a mish-mash of two data types together, basically a compromise b/w a linked-list and a vector.
    What if you have moderate-sized arrays that link to each other?
    Array[10]->Array[10]->Array[10]->... and so on?
    i) This way, you don't have to make as many hops for reaching an element. MishMash[35] is actually just two hops away, rather than 35 hops!
    ii) You still have to allocate a new buffer for every 10 inserts (this could also grow exponentially), but you don't need to copy the old buffer.
    I feel like this data type can be used for vectors that dramatically alter in size frequently.

  • @ianpan0102
    @ianpan0102 3 ปีที่แล้ว +1

    Would love to see a video on creating class String from scratch!

  • @HattoriHanzo031
    @HattoriHanzo031 2 ปีที่แล้ว +2

    Great video! It looks to me that there is a potential memory leak in ReAlloc function if new capacity is smaller than size, Desctructors will be called only on first newCapacity elements, or am I missing something?

  • @jasonzhang4632
    @jasonzhang4632 3 ปีที่แล้ว

    Great video thanks

  • @timhaynes6735
    @timhaynes6735 ปีที่แล้ว

    I implemented mine such that the container is also a shared pointer, and used the placement new approach in the first pass. Also the memory is coming from a "memory manager" that allocates it from some internal heaps and you can specify which heaps you want to use at instantiation. I do wonder if the Realloc step could just use memcpy instead of calling placement new and moving each element from the "old" container buffer to the "new" one.

  • @JxcksonSF
    @JxcksonSF 3 ปีที่แล้ว +1

    Yeah, everyday videos 🤩

  • @shaiavraham2910
    @shaiavraham2910 3 ปีที่แล้ว +3

    Can you make a video explaining your coding style and naming conventions?
    I think it would be cool to see a little video about why you prefer PascalCase and prefixes on variables (like m_ and s_) and what are your tips for choosing naming and coding conventions.
    It would also be cool if you could talk about your C# conventions as well (as far as I know, the m_ prefix isn't very popular in C#, so I think it would be cool to know if you stick to it and why).

    • @leocarvalho8051
      @leocarvalho8051 3 ปีที่แล้ว

      He once said that he used to use camelCase back when we was doing java but that after sometime at EA he got so much used to PascaCase that he cant use camelCase anymore (sorry bout my english)

    • @KarolSzapsza
      @KarolSzapsza 3 ปีที่แล้ว +1

      Choose what do you personally prefer (or make a consensus within the team you are working with). Some IDEs (e.g. CLion or VS w/ReSharper) allow to set preferred naming conventions in Settings and they will underline inconsistently named variables etc. Big companies have some variable naming (and code formatting) standards, you can find them easily, search "Mozilla C++ coding style", "Google C++ Style Guide" etc.

  • @joaopedrovoga5497
    @joaopedrovoga5497 2 ปีที่แล้ว

    This was harder than I expected.

  • @NettoRockman
    @NettoRockman 3 ปีที่แล้ว

    Yes please, video on variadic templates

  • @Mr.Freemen_G
    @Mr.Freemen_G หลายเดือนก่อน

    Спасибо тебе! Для начинающего трудно, но очень интересно! Хотя предыдущее видео понятнее про массивы.... Спасибо!

  • @MrBlawkEyes
    @MrBlawkEyes 9 หลายเดือนก่อน

    40:13 Constructors are being called there if you do a cout in your constructors you will see them print. But I assume the point being that they don't need to be called so thats why we switch to an operator new.

  • @sudheerinbloom
    @sudheerinbloom 3 ปีที่แล้ว

    Very nicely explained. Pls do consider sharing the code so that we can re-look at it. Thanks.

  • @Yupppi
    @Yupppi 7 หลายเดือนก่อน

    I tried to figure out an function to do the doubling of the capacity initially, but heavily dampening as the capacity grows, but nothing was really that satisfying. Like it'd always still grow quite a lot once it reached like 500. Which is obviously quite unnecessary as you'll take forever to fill it even if you had that much more data. Or it wouldn't grow a lot in the beginning which is also the opposite of what you'd want to. Without doing if checks for the size, that'd also be the opposite of what we want, building processing cost trying to save it.

  • @mcdamastr3604
    @mcdamastr3604 3 ปีที่แล้ว

    Thanks for the great video/exercise! - Although I have noticed something that I am quite confused about. In your Vector class, you create a pointer to the heap-allocated array containing the objects in the vector, then use that pointer whenever you are directly accessing/changing the objects/size of the array. Wouldn't it be easier to create the pointer, then have a reference to the pointer, and use the reference when you can and use the pointer when necessary (e.g. deleting memory, reallocating memory). This should work since the reference will always be pointing to the pointer (dereferenced), and when reallocating memory, the pointer's contents will be different, but the place of memory which holds that pointer will be the same, so the reference to the pointer is not changing. The reason I'm thinking this is because, in your references video, you said to always use a reference if you can, and only use pointers when necessary. If this is a bit confusing, here is what I mean: . // Example class Vector public: // All the public methods and things private: T *m_data_ptr = nullptr; // Create pointer to array containing vector objects/elements (currently set to nullptr) T &m_data_ref = *m_data_ptr; // Reference to dereferenced pointer to array containing vector objects/elements // Use m_data_ref when possible . Is this a good thing to do?

    • @benlennart4481
      @benlennart4481 3 ปีที่แล้ว

      It would not work, because the one thing you cannot do with references is changing what they are referring to. That means, if you have to reallocate the buffer, your reference will always reference the old buffer you already have deleted.

  • @silurust
    @silurust 3 ปีที่แล้ว

    It is a very good idea at the beginning of the video to encourage viewers to go on and implement their own vector class. However, to help get people started you may perhaps give a little push by also giving what it should be capable of (methods? interface? header file? a code segment that uses a vector and can successfully compile and run if someone has implemented a vector class correctly). Otherwise, a very adventurous viewer may start implementing something huge and never returning to your video. Or a passive kind just shrug their shoulders and go on watching without spending a second on thinking how it could be done. Or, alternatively or supplementing the previous idea, you can also set a time limit: "let's see how many of the following methods/capabilities you can implement in 30 mins or 60 mins. (a time-limit in most cases can help focus.)

  • @andreasenglert1723
    @andreasenglert1723 ปีที่แล้ว

    Thx for the video. How did you do, what you did at 22:14? (initializer list without typing)

  • @devsirat
    @devsirat 3 ปีที่แล้ว

    Thanks

  • @aquavitale3551
    @aquavitale3551 3 ปีที่แล้ว +6

    just can't help waiting for rbtree-based set explained by The Cherno

    • @damnstupidoldidiot8776
      @damnstupidoldidiot8776 3 ปีที่แล้ว +2

      rbtree-based set gives me PTSD.

    • @dominicjung4950
      @dominicjung4950 3 ปีที่แล้ว +2

      me too. I was able to do well upto AVL tree but RB tree is different kinda beast... got stuck while trying to understand how deletion works in RB tree.

    • @aquavitale3551
      @aquavitale3551 3 ปีที่แล้ว +2

      @@dominicjung4950 absolutely. deletion is kinda magic, and most of tutorials skip this thing

    • @damnstupidoldidiot8776
      @damnstupidoldidiot8776 3 ปีที่แล้ว +1

      @@aquavitale3551 It requires very weird recolouring but you can go on geeksforgeeks it explains it quite well.

  • @Gamerzhut
    @Gamerzhut 2 ปีที่แล้ว

    @The Cherno , I like your videos man , I was wondering if you can make a video about 2D dynamic array where the size of it (int n,m) are in private and the array itself is in private , I don't know how to make it inside the public class , can you help me with that ?

  • @billowen3285
    @billowen3285 3 ปีที่แล้ว

    I literally just did this myself last week haha

  • @flexw
    @flexw 3 ปีที่แล้ว

    I enjoy your videos but could there be a memory leak in the ReAlloc Function? If the move constructor throws, then I think, newBlock gets lost. Is there any policy that says that move constructors are not permitted to throw?

  • @Tal__Shachar
    @Tal__Shachar 3 ปีที่แล้ว +2

    OMGGG NEW CHERNO VIDEO AND IT'S 45 MINUTES LONG IM SO FREAKING EXCITED OMG

  • @ChlorieHCl
    @ChlorieHCl 3 ปีที่แล้ว +2

    High quality video as always! Those object lifetime issues are really nasty, which always make me appreciate the work of our STL implementors more. Apart from a proper Rule of Five in the vector class, other features like standard allocator & iterator support and stronger exception guarantees, though tricky to implement, are also needed for a complete vector class. I would really appreciate it if you could cover these topics. Again thanks for your good work!

    • @SuviTuuliAllan
      @SuviTuuliAllan 3 ปีที่แล้ว +1

      Here's a tip: if you can code slowly, you can code quickly.

    • @ChlorieHCl
      @ChlorieHCl 3 ปีที่แล้ว +1

      Suvi-Tuuli Allan But sacrilegious code is often not permitted XD

  • @lored6811
    @lored6811 3 ปีที่แล้ว

    What are the benefits of overloading operators for a vector class? Wouldn't that make many things super confusing? Is V1 * V2 the Dot or the Cross-Product?
    What do you guys think about OO?

  • @Diego-Garcia
    @Diego-Garcia 6 หลายเดือนก่อน

    Holy, C++ is complex as duck! Now I understand why Linus doesn't want it in the Linux kernel. Imagine debugging a code with this complexity that wasn't made by you. The implicit things you need to be aware of...

  • @ShivamJha00
    @ShivamJha00 3 ปีที่แล้ว

    Moreeeee data structure videos please :D

    • @mateuszabramek7015
      @mateuszabramek7015 3 ปีที่แล้ว

      "Moreeeee" reads Mori like death 💀 it corresponds with your avatar. Coincidence?

  • @silverqx
    @silverqx 3 ปีที่แล้ว +2

    new(&m_Data[m_Size]) T(std::forward(args)...); how cools is that 😂 that's awesome 😎 I didn't know that I can invoke new operator like that, thx ✌
    By the way, examples like this are the best how to learn and understand how underlying std library works. 👍

    • @tzimmermann
      @tzimmermann 3 ปีที่แล้ว +1

      That's called "placement new", and it is indeed really powerful! Have a look at memory pooling and custom allocation, the whole subject is quite interesting.

  • @bulentgercek
    @bulentgercek 3 ปีที่แล้ว

    Thanks

  • @VivekYadav-ds8oz
    @VivekYadav-ds8oz 3 ปีที่แล้ว +2

    But what if you call Clear() on the object, and then when the object goes out of scope, its destructor calls Clear() too, leading to the same error again?

  • @stancartmankenny
    @stancartmankenny 3 ปีที่แล้ว

    Could you do a video showing how to solve the halting problem?

  • @JuanGarcia-lo2el
    @JuanGarcia-lo2el 3 ปีที่แล้ว

    Have you ever implemented triangulation algorithms like Delaunay triangulation?

  • @5ko99
    @5ko99 2 ปีที่แล้ว +3

    I think there is a bug in reallocate function. If we enter in that if statement :
    if (new_capacity < m_size)
    m_size = new_capacity;
    then I think in for loop when we call destructor of each element, then if old m_size is bigger then new m_size then I think we do not call destructors of all elements.
    Correct me if I'm wrong.
    Great job btw :)

    • @tri--
      @tri-- ปีที่แล้ว

      Yeah, that's true. This is very scary because it can lead to memory leaks if the T object is supposed to free some memory in the destructor.

    • @xtriangleboi
      @xtriangleboi ปีที่แล้ว

      Possible fix: At the start, save the current size. After the loop, enter in a new loop starting from the current size till the previous size. Then call destructors for those.

  • @jorisbaranauskas9326
    @jorisbaranauskas9326 3 ปีที่แล้ว

    How should I return a range of the vector?
    Vector getRange(size_t startIndex, size_t count) const
    {
    Vector tempVector= Vector();
    for (size_t i = startIndex; i < startIndex + count; i++)
    tempVector.pushBack(std::move(this->itemsArray[i]));
    return tempVector; // This is wehre it calls "tempVector" destructor
    }
    Because it deletes tempVector via destructor and then returns empty vector.

  • @koonhanong2267
    @koonhanong2267 9 หลายเดือนก่อน

    42:06 line 98-99 calling the destructor on m_Size works if newCapacity >= m_Size. But if newCapacity < m_Size, you might miss out destructing some objects in m_Data?

  • @theb1rd
    @theb1rd 3 ปีที่แล้ว +5

    This is a bug:
    newBlock[i] = std::move(m_Data[i]);
    "newBlock" is uninitialized memory - calling move assignment method will likely lead to a crash (depending on T).
    Do this instead, using the move-constructor:
    new (newBlock + i) T(std::move(m_Data[i]));

    • @arnaudgranier3045
      @arnaudgranier3045 3 ปีที่แล้ว

      Yes I don't know about you but I get a runtime error with the original code and I ended up with the same conclusion.
      For some reason, The Cherno does not seem to have this issue...

    • @theb1rd
      @theb1rd 3 ปีที่แล้ว

      @@arnaudgranier3045 Either the compiler is zeroing the memory for him (which would just happen to work for a lot of objects, if all zeros are a valid state), or he got lucky. A proper debug build would initialize that memory to 0xfefe to shine a light on this bug.

  • @nailbomb420
    @nailbomb420 3 ปีที่แล้ว

    off topic, but does anyone know what theme Cherno uses? I find the oranges and other colours quite appealing but haven't been able to find a match.

  • @technologicalwaste7612
    @technologicalwaste7612 3 ปีที่แล้ว

    pls make a video on using pmr (monotonic) with constexpr container
    thx

  • @TopConductor
    @TopConductor 3 ปีที่แล้ว

    is this code available to check somewhere? I haven't quite understood the last part with delete with non trivial data types and variadic templates thing.

  • @darshitnasit3130
    @darshitnasit3130 3 ปีที่แล้ว +2

    I have added more constructors which takes arguments as initializer_list :
    1. Vector(const std::initializer_list&);
    2. Vector(std::initializer_list&&);
    Then I have created a Student class and created three objects of it s1,s2,s3
    And then I try to do following:
    Vectorstudents = { s1, s2, s3};
    Vectornumbers = { 1,2,3,4,5,6,7,8,9 };
    So as I am passing s1,s2,s3 as "lvalues" for students and 1,2,3,... as "rvalues" for numbers.
    But in both of cases it is calling 2nd constructor. So why Vectorstudents also calling 2nd constructor? Can you help me ?

    • @hobajt
      @hobajt 3 ปีที่แล้ว

      I think it's because in both cases you're still initializing the vector with temporary instance of initializer_list (so r-value). If you want to call the l-value constructor, you'd have to do something like:
      std::initializer_list list = { s1,s2,s3 };
      Vector students = list;

  • @Elreydelacolina1
    @Elreydelacolina1 3 ปีที่แล้ว

    smart pointers can be used instead of C style pointer?

  • @raja28chowdhury
    @raja28chowdhury 3 ปีที่แล้ว

    i love your video :d

  • @afterlife1578
    @afterlife1578 ปีที่แล้ว

    for anyone getting a bug for making a string vector, he has addressed the issue in the writing an iterator video.

  • @snookiewozo
    @snookiewozo 3 ปีที่แล้ว +7

    "Hopefully bug-free" yup, try using it with std::string

    • @Albert-px4jo
      @Albert-px4jo 3 ปีที่แล้ว +1

      Yeah. How to resolve if the template argument is std::string, the program still crash

    • @betterfly7398
      @betterfly7398 3 ปีที่แล้ว

      hmm, why would it? std::string is responsible for it's own allocations and deallocations, and as long as the vector doesn't call the destructor twice, then it wouldn't.

  • @victorhugomagalhaes6370
    @victorhugomagalhaes6370 3 ปีที่แล้ว

    Please, make a vídeo about Vector vs List arrays. Thanks for sharing your knowledge with us.

    • @user-dh8oi2mk4f
      @user-dh8oi2mk4f 2 ปีที่แล้ว

      What is a list? Lost has many meanings in programming. If you don’t specify which list you mean, it can be difficult to figure out what you mean.

    • @victorhugomagalhaes6370
      @victorhugomagalhaes6370 2 ปีที่แล้ว

      @@user-dh8oi2mk4f list in c++ is literally a list. Don't need be more specific

    • @user-dh8oi2mk4f
      @user-dh8oi2mk4f 2 ปีที่แล้ว

      @@victorhugomagalhaes6370 You said "list arrays", and I got confused because in c++ the standard list is not an array, it is a linked list, which is an entirely different data structure.
      As for your original question, it is completely dependent on the context. Arrays/Vectors have much faster access time, but linked lists have much faster insertion and deletion.

  • @karamu451
    @karamu451 3 ปีที่แล้ว +2

    If anyone else is confused to why std::string isn't working, my understanding is that in the PushBack function or wherever you're setting values in m_Data you actually need to placement new the object into place not use the assignment operator here. Basically you'll wanna replace
    m_Data[INDEX] = newValue;
    TO
    new(&m_Data[INDEX]) newValue
    I'm fresh to this idea so if anyone has a better description of why, it'd be much appreciated. Thanks!

    • @carsten.svanholm
      @carsten.svanholm 2 ปีที่แล้ว

      Try this
      void PushBack(T&& value)
      {
      if (m_Size >= m_Capacity)
      Realloc(m_Capacity + m_Capacity / 2);
      new(&m_Data[m_Size]) T(std::move(value));
      m_Size++;
      }

  • @aryanparekh9314
    @aryanparekh9314 3 ปีที่แล้ว

    At 43:17 cherno realised C++ is a weird language and you could techinally call a destructor of an int typename 😂

  • @lyricsmint567
    @lyricsmint567 3 ปีที่แล้ว

    Hey the Cherno, kindly sequence the DS videos in Dedicated playlist

  • @GeeksPlayOfficial
    @GeeksPlayOfficial 3 ปีที่แล้ว

    Would you please do Maps? Thank you

  • @UsernameUsername0000
    @UsernameUsername0000 10 หลายเดือนก่อน

    Would setting all pointers to heap memory in the destructors to nullptr also solve the problem at the end of the video?

  • @augustin7105
    @augustin7105 3 ปีที่แล้ว +1

    Now I have an excuse to sleep..
    Data Strucure..

  • @kfossa344
    @kfossa344 3 ปีที่แล้ว +1

    Don’t know the first thing about any of this but here I am.

  • @AgentM124
    @AgentM124 3 ปีที่แล้ว

    I love how C++ has so many crazy symbol combinations and such that make it look super crazy difficult, but you explain it very well.

  • @user-fm9gn5wh1d
    @user-fm9gn5wh1d 7 หลายเดือนก่อน

    34:00 If we use "new", don't we need to have a "delete" somewhere too? To avoid memory leak?

  • @sanjeevsaharan
    @sanjeevsaharan 3 ปีที่แล้ว

    Doesn't assignment operator will be called while push back instead of copy ?

  • @fernandoiglesiasg
    @fernandoiglesiasg 3 ปีที่แล้ว

    Good point about using directly raw pointers in this type of cases (around the start of minute 15)! It got me thinking, just for the fun of understanding, how would a smart pointer (std's unique_ptr or shared_ptr) substitute the T* newBlock = new T[newCapacity]?

    • @mridgewell
      @mridgewell 3 ปีที่แล้ว +1

      You can do it like this:
      std:: unique_ptr newBlock = std::make_unique(newCapacity);
      The advantage of this is it will call the correct version of the delete operator for you! However, I would still use raw pointers if I'm writing a custom container.

    • @benlennart4481
      @benlennart4481 3 ปีที่แล้ว

      If the move assignment (which should really be a placement new to call the constructor) throws an exception, newBlock will not be deleted and you leak memory. A unique_ptr would prevent that. However, in that particular case, there should be a try-catch-block to ensure destructors are called on exactly those elements that have been succesfully move constructed. The more you think about it, the harder it gets to make this function bug free. In many other cases unique_ptr would be a great help, but not here.

  • @ihormoroz5652
    @ihormoroz5652 3 ปีที่แล้ว

    I'd love to hear if I can free part of my vector without having to move/copy the whole thing. Something I would do with realloc(m_Data, (m_Size - 1) * sizeof(T)) in C. Is there something like this in c++?

  • @dmytroboiko1
    @dmytroboiko1 6 หลายเดือนก่อน

    I did my own implementation using std::move(), it works fine on reallocating, but only in the release mode, and crashes with "heap corrupted" error in the debug mode.

  • @user-hz4tc2pf3x
    @user-hz4tc2pf3x 3 ปีที่แล้ว +1

    0:25 Okay I can't take 4 dimensions anymore. I need to see how it looks. So I'm going to challenge you to create a 4D renderer. (I think it's suitable because you like graphics programming the most, correct me if I'm wrong.)

    • @algorythm4354
      @algorythm4354 3 ปีที่แล้ว +1

      Not all the dimensions need to refer to physical dimensions. The fourth dimension is usually time ;)

  • @colinmaharaj
    @colinmaharaj ปีที่แล้ว

    Can I write a templated dynamic array that can be saved to and loaded from disk?

  • @BohemianDoor
    @BohemianDoor 3 ปีที่แล้ว

    Getting an segmentation violation signal in the push_back function and have no idea why.
    All i'm getting is that is is caused by a READ memory access, which is m_Data[m_size] = value;

  • @JohannesEckhoff
    @JohannesEckhoff 3 ปีที่แล้ว

    Since you no longer need to call constructors and destructors in the ReAlloc function, could you use memcpy instead of looping and copying each element one by one?

    • @TheExstud
      @TheExstud 3 ปีที่แล้ว +1

      No, at least not always, suppose in your constructor you store the this pointer in some member variable. The memcpy would copy over the old/invalid pointer. I just ran into this.

  • @legotecnico
    @legotecnico 3 ปีที่แล้ว +2

    very interesting video and series really! I have one comment though. In your Vector3 class implementation
    of the move assignment operator (line 41) I think you should call delete m_MemoryBlock before assigning other.m_MemoryBlock to it, otherwise a memory leak is created. Correct? But then, if you do so, each time you move a Vector3 element to the vector (PushBack of ReAlloc function)
    you get a memory access violation because you are moving the element to an uninitialized memory block and the delete m_MemoryBlock in Vector3 move assigment fails.
    To solve that I think it is necessary to initialize to 0 the memory allocated with ::operator new every time this is used, with something like std::memset(m_data, 0, m_capacity * sizeof(T));
    In this way the delete is called on a nullptr and does not fail. Am I wrong? Thanks.

    • @1996robinC
      @1996robinC 3 ปีที่แล้ว

      Yes, you're a lifesaver! I had this exact issue while trying this Vector class out with my own implementation of String, it would indeed crash when calling the move assignment operator was called on non-initialised memory.
      However I still found a case for a crash: when calling pop_back, my own String deleted its m_Data block but did not set it to nullptr; So when calling push_back again afterwards, the same memory access violation happens. The fix was to memset to zero also on pop_back() and on clear(). Another fix would be to edit my String destructor to set the m_Data to nullptr, but I find it a cleaner solution to do this within Vector.
      EDIT: he addresses this at the end of the "Writing an iterator in C++" video. The clean solution to fix this issue is with "placement new" construction (like used in emplace_back) instead of the assignment operator.