Classes part 3 - Copy Constructor, Copy Assignment(Deep and Shallow Copy) | Modern Cpp Series Ep. 39

Поделиться
HTML-код
  • Опубликовано: 10 сен 2024
  • ►Full C++ Series Playlist: • The C++ Programming La...
    ►Find full courses on: courses.mshah.io/
    ►Join as Member to Support the channel: / @mikeshah
    ►Lesson Description: In this lesson I cover the copy constructor, and copy assignment operator. I start by showing how the compiler gives you these two special functions for classes for free, using the compiler generated ones. Unfortunately, this is not sufficient, as when we have to dynamically allocate memory, the trivial copy can result in problems like double frees or unwanted sharing of data. Next I show you how to avoid making these 'shallow' copies, and write your own copy constructor and copy-assignment operators to perform a deep copy.
    ►RUclips Channel: / mikeshah
    ►Please like and subscribe to help the channel!

Комментарии • 88

  • @kenk4552
    @kenk4552 Месяц назад

    Does "Array myArray2 = new Array(myArray); " triggers copy-constructor as well?? If yes, I assume the difference is allocating myArray2's memory on heap?

    • @MikeShah
      @MikeShah  Месяц назад +1

      I might need to see a working example of this -- meaning:
      Array on the left-hand side needs to be a pointer. You can certainly override the new operator and pass in a type.
      However, with a normal copy constructor (e.g. Array myArray2 = myArray) -- the copy constructor would take care of the deep copy, and likely allocate on the heap any memory needed.
      There's something called 'placement new' otherwise (slightly different syntax) that otherwise can allocate in already allocated heap memory.

    • @kenk4552
      @kenk4552 Месяц назад +1

      @@MikeShah For example:
      template
      struct eigen_base {
      T* components_;
      eigen_base() {
      components_ = nullptr;
      }
      eigen_base(const eigen_base& other) {
      this->components_ = other.components_ ? new T(*other.components_) : nullptr;
      }
      eigen_base(const T& other) {
      this->components_ = new T(other);
      }
      eigen_base& operator=(const eigen_base& other) {
      if (this != &other) {
      this->components_ = other.components_ ? new T(*other.components_) : nullptr;
      }
      return *this;
      }
      ......
      };

    • @kenk4552
      @kenk4552 Месяц назад +1

      What does "new T(xxxx)" trigger?

    • @MikeShah
      @MikeShah  Месяц назад +1

      ​@@kenk4552I think I understand the question now, so I wrote an example as well. It calls the copy constructor and heap allocates the object.
      godbolt.org/z/6oGMe96Tv
      #include
      struct Type{
      Type(){
      std::cout

    • @kenk4552
      @kenk4552 Месяц назад +1

      @@MikeShah Great great example !!!! Thank you so much for putting in time to respond to every single one of our questions !! Huge respect!

  • @noelgallagher7887
    @noelgallagher7887 Год назад +10

    Wow, I dont understand how this is not 100k+ views, this is by far the best explanation I"ve seen of this concept !

    • @MikeShah
      @MikeShah  Год назад

      Cheers, thank you for the kind words!

  • @atlasflare7824
    @atlasflare7824 2 года назад +9

    Thanks for publishing these videos to public. Your teaching style is fantastic.

    • @MikeShah
      @MikeShah  2 года назад

      Thank you for the kind words!

  • @astbast1966
    @astbast1966 8 месяцев назад +2

    This is the best c++ playlist on youtube by far!!!!

    • @MikeShah
      @MikeShah  8 месяцев назад

      Thank you for the kind words 🙏

  • @punchline1729
    @punchline1729 6 месяцев назад +1

    Fantastic tutorial, as I'm learning UE5 C++, this tutorial is helping me a lot to understand what is happening there

  • @sallaklamhayyen9876
    @sallaklamhayyen9876 Год назад +2

    You are a great teacher thank you so much for this valuable content
    please continue

    • @MikeShah
      @MikeShah  Год назад

      Cheers, you are most welcome!

  • @crazymemes4080
    @crazymemes4080 5 месяцев назад +2

    Omgg 😮 this is c++ goldmine so excited to complete this playlist.
    Request: please make videos on building tools using c++ , I always want to develop something using c++ but dunno how to start, thanks man.

    • @MikeShah
      @MikeShah  5 месяцев назад

      Cheers! This may be a good starting point for a small project -- courses.mshah.io/courses/quick-start-introduction-to-modern-c-image-loader

  • @VoidloniXaarii
    @VoidloniXaarii Месяц назад +1

    So thankful for all your amazing lessons

    • @MikeShah
      @MikeShah  Месяц назад +1

      Cheers, you are most welcome! Happy to have you as part of the community!

  • @embeddedMikeTV
    @embeddedMikeTV 3 месяца назад +1

    Interesting channel. C++ topics are very well explained here.

    • @MikeShah
      @MikeShah  3 месяца назад +1

      Cheers -- welcome aboard!

  • @vimalathithand917
    @vimalathithand917 5 месяцев назад +2

    Damn ! Such a clear and wonderful explanation.! You deserve much more views and subs sir...!
    It would be very useful if you could do a video on namespace , scope of variablesand functions in namespace, inline keyword and how scopes and lifetimes of identifiers defined in different circumstances and the best practices to be used in header files!
    And im a bit confused between difference between file scope vs global scope and gobal namespace parent namespaces. It'd be of great help if you could enlighten me ! Thanks a lot!!

    • @MikeShah
      @MikeShah  5 месяцев назад

      Cheers! I have a few videos on scope, inline, and more in the playlist 🙂

    • @vimalathithand917
      @vimalathithand917 5 месяцев назад +1

      @@MikeShah sure I'll check them out and thank you so much for these!😊

  • @reptilicusrex4748
    @reptilicusrex4748 Год назад +2

    Thanks for making this video. It's an excellent explanation.

    • @MikeShah
      @MikeShah  Год назад

      Cheers, thank you for the kind words!

  • @ranaobeidat-vm1fy
    @ranaobeidat-vm1fy Месяц назад +1

    Thank you , you are the best

  • @Quancept
    @Quancept 11 месяцев назад +4

    Mike, a quick question. In the copy assignment function why do we delete[] before assigning new heap area for the new data object? delete[] operation marks the area as free right, thereby making the data pointed by the original object a dangling pointer? Am I missing something here? Please help! Thanks

    • @MikeShah
      @MikeShah  11 месяцев назад +2

      We delete[] first because during assignment we are potentially copying to an array of a different size (not in this example since the array is always 10 integers, but this is just an example). If we don't free the memory, before allocating again, then we are left with a memory leak.

  • @justcurious1940
    @justcurious1940 4 месяца назад +1

    Great explanation Mike Thanks.

  • @dhanushs1802
    @dhanushs1802 2 года назад +2

    Very neatly explained as always. Thank You

  • @mfc1190
    @mfc1190 Год назад +1

    Just wanted to stop by and see you're awesome! I just started learning C++ coming from python and Go and your videos have really helped me. They are currently my main source of learning! Thanks for the great content.

    • @MikeShah
      @MikeShah  Год назад

      Cheers, thank you for the kind words!

  • @deepblackoutlaw9640
    @deepblackoutlaw9640 7 месяцев назад +1

    My go-to resource for C++ tutorials, you're the best! 📚🙌

    • @MikeShah
      @MikeShah  7 месяцев назад +1

      Cheers! Thank you for the kind words 🙏

  • @sowmya2217
    @sowmya2217 11 месяцев назад

    Hi Mike, Thank you for the video. This is the best video that i watched which explains both copy constructor and copy assignment operator clearly.

  • @hossamalzomor3311
    @hossamalzomor3311 Год назад +3

    Thanks for the clear explanation
    But do we need to delete the allocated memory and reallocate it again in the copy assignment operator?

    • @MikeShah
      @MikeShah  Год назад +3

      Need to remove the previously allocated memory, for which we are going to copy over. This step is not always strictly necessary in special cases where we for example have a dynamically allocated array of the same size -- we could just copy elements over that allocated memory. That said, in our copy constructor, we need to make sure that we perform a 'deep copy' to own our memory in our object, and it's generally a good idea to remove any previously allocated resources.

  • @joebosah2727
    @joebosah2727 Год назад

    Thanks, Prof
    Can’t get enough
    MasterClass
    Kept revisiting
    Quite clear in my head

    • @MikeShah
      @MikeShah  Год назад

      Cheers, you're most welcome Joe!

  • @sauravshaw6965
    @sauravshaw6965 2 года назад +2

    Hey Mike! Thanks for the videos can you explain why we need to return as Array& , we can simply use Array right?

    • @MikeShah
      @MikeShah  2 года назад +6

      We return Array& in the copy-assignment operator (i.e. operator= function). If you look carefully at the return value, you'll notice it as '*this'. 'this' is the internal pointer to the current instance of the object. We derference that object, and return the actual object, that is, not the actual pointer. Because we are doing an actual assignment of an object, we need to return a reference type, that is, Array&.

    • @sauravshaw6965
      @sauravshaw6965 2 года назад +1

      @@MikeShah Thanks for the explanation!!

  • @johnmckown1267
    @johnmckown1267 2 месяца назад +1

    Thinking back to previous video, what if the pointer were a unique pointer? Before you made the copy constructor?

    • @MikeShah
      @MikeShah  2 месяца назад +1

      Copies of unique pointers as you mentioned are forbidden. You'll find something here in cppreference on it not being copyassignable en.cppreference.com/w/cpp/memory/unique_ptr. So whatever your type is, you can do move construction or move assignment with unique pointers, but no copies allowed because by definition that means you'd have two unique_ptrs sharing the same data. So that was a long winded way of me just saying, you'll do the 'deep copy' yourself with a unique_ptr just like you would with a normal pointer :)

  • @syed6044
    @syed6044 2 года назад +2

    Hi Mike, At 12.25 , referring to the class Array. Question is When in main function control will reach at myArray.printingData(); how and why this pointer will point to the data created on the heap using the data = new int[10];

    • @MikeShah
      @MikeShah  2 года назад

      As soon as the array is constructed at line 23, the constructor executes and allocates new int[10]. Each instance of 'Array' (i.e. myArray in this example) has its own member variable associated with it (in this case there is one member variable data in the class). Let me know if that's helpful. If you want to see how this is implemented, I have a C lesson giving an idea on how Object-Oriented programming is implemented: ruclips.net/video/cR2QFQbssa0/видео.html

  • @user-wc6zg7sz9l
    @user-wc6zg7sz9l 5 месяцев назад +1

    Hey Mike! Thanks for the awesome videos!
    At 24:55 line 20, can you explain why we can directly access rhs's (the argument we passed in the copy constructor) data member (int* data) which is declared as private in the class declaration? I thought we need to use something like getter in copy constructor just like we can't directly set it so we need SetData function and use it in the main function.
    Thanks in advance!

    • @MikeShah
      @MikeShah  5 месяцев назад +1

      Since we have passed in the 'rhs' by reference, it is the actual values. Pass by reference avoids making a copy, so we access the actual data. Since this is of the same type (i.e. rhs is also of type 'Array'), we can access the private variables :)

  • @aslichg
    @aslichg 11 месяцев назад +1

    Very nice explainations again. Thanks
    Just one question. Inside copy assignment operator, we have first if statement and it checks if &rhs==this; return *this. So here rhs is from first object and “this” is from the second object of the class"?. How can we know where is “ this “ beforehand. Because we are deleting data after if statement and creating new data on the heap then return by dereferencing “this”.
    I hope my question makes a sense.
    But still, If my question is not clear, that would be great if you could explain one more time first if statement inside copy assignment operator. Why do we return *this if the staement is true?

    • @MikeShah
      @MikeShah  11 месяцев назад +3

      We need to return some value -- effectively it's saying 'don't go through the effort of doing a potentially expensive copy if we are in fact attempting to copy ourselves'.

  • @moderig
    @moderig 2 месяца назад +1

    Thanks for the informative video once again! Was wondering when discussing the order of free operations when array1 and array2 go out of scope, would it actually be the case that array2 is deleted first due to the nature of the stack, meaning it deletes array1s data before array1 even gets the chance?

    • @MikeShah
      @MikeShah  2 месяца назад +1

      Do you have a timestamp? (I'm assuming myArray and myArray2 within the main() for my response) -- the answer is that objects are destroyed in a Last In, First Out (LIFO) style, so myArray2 indeed is destroyed first. This is deterministic in C++, and it will always follow this order :)

    • @moderig
      @moderig 2 месяца назад +1

      @@MikeShah Yes that is the example. Thank you so much for the clarification and once again thanks for the playlist! Coming from C it's been really rewarding watching these videos.

    • @MikeShah
      @MikeShah  2 месяца назад +1

      @@moderig cheers!

  • @aymanedihaj
    @aymanedihaj 11 месяцев назад

    thank you:)

  • @alphastein1123
    @alphastein1123 3 месяца назад +1

    Dr. Shah, can I ask about ur opinion to learn CUDA C++ for computer graphics and computer vision as a final year bachelor student just about to start a career ?
    Or this is lower priority to learn than other things ?
    and really THANK YOU Dr. Shah

    • @MikeShah
      @MikeShah  3 месяца назад

      I think CUDA would be a wonderful skill to learn in your case. It teaches another way to think about computation 🙂

  • @ThislsYusuf
    @ThislsYusuf Год назад +1

    Hi Mike, how would you go about declaring the copy assignment operator in an interface (.hpp) and its corresponding implementation (.cpp)? I'm following the tutorial using this format and I seem to have hit a syntactical roadblock.

    • @MikeShah
      @MikeShah  Год назад +1

      Copy Assignment operator in the .cpp would be something like: Array& Array::operator=(const Array& rhs){ ... }

    • @ThislsYusuf
      @ThislsYusuf Год назад

      @@MikeShah got it. I also realized you already had the answer in the next video in the series. Thanks a mill.

    • @MikeShah
      @MikeShah  Год назад

      @@ThislsYusuf cheers!

  • @MrSals123
    @MrSals123 Год назад

    Hello Dr. Shah, awesome lecture!! Just a question, why do we need to delete [] data in the copy constructor? Since the object is not initialized yet why would data be pointing to something?

    • @MrSals123
      @MrSals123 Год назад +2

      Got it, clarified later in the video

    • @MikeShah
      @MikeShah  Год назад

      @@MrSals123 Cheers!

  • @panicse
    @panicse 7 месяцев назад

    Hi Mike,
    I have a question about copy constructor. As i understood when you created second object copy constructor was called. No data was allocated to second object before. Is it valuable to write delete[] data; inside copy constructor (after that you create dynamic array)?? I Think that this delete[] gives us nothing, but maybe im wrong 😊 Thanks!

    • @MikeShah
      @MikeShah  7 месяцев назад +1

      For operator= the object has already been initialized once, so it is important to delete.The 'copy constructor' (named same as the function) otherwise is initializing the object for the first time, so no need to delete anything.

  • @TechTricks1992
    @TechTricks1992 11 месяцев назад +1

    Why to delete data in assignment operator when it is having a allocated memory. Can't we just copy new elements from source object to data memory directly

    • @MikeShah
      @MikeShah  11 месяцев назад

      If the allocation is the same size, we certainly would not have to delete it -- so for this video it's true we always have 10 ints. Keep in mind, that is for demonstration purposes, we'll have to delete old data and then reallocate a new buffer to put memory in if size is different (of course if new allocation is smaller, you could also track capcity/length and make other decisions as needed.)

    • @TechTricks1992
      @TechTricks1992 11 месяцев назад

      @@MikeShah ok, thanks for your reply. It was a great video.

    • @MikeShah
      @MikeShah  11 месяцев назад

      Cheers! @@TechTricks1992

  • @Sukhraj_3301
    @Sukhraj_3301 3 месяца назад

    Hi sir, at 25:14, how do we say that myArray2 specifically called the copy constructor ?

    • @MikeShah
      @MikeShah  3 месяца назад

      myArray is being 'created by copy' -- thus the copy constructor is invoked as the new object 'myArray2' is being created for the first time. This is not to be confused with the 'assignment operator (i.e. operator=)' -- we are infact invoking the copy constructor at line 41 at 25:14

  • @peerajak
    @peerajak 4 месяца назад +1

    Hi, I just found out that a = b; had called operator = instead of copy constructor. Am I correct?

    • @MikeShah
      @MikeShah  4 месяца назад +1

      Correct! Becase a is already constructed -- i.e. you construct a new type when the type declaration is to the left of the type (e.g. 'Student a;' calls the constructor, 'Student a = b' 'would call the 'copy constructor' to make a as a copy of b during construction)

    • @peerajak
      @peerajak 4 месяца назад +1

      @@MikeShah Thank you. This explanation is precious ❤️

    • @MikeShah
      @MikeShah  4 месяца назад

      Cheers! ​@@peerajak

  • @dwivedys
    @dwivedys 3 месяца назад

    Thank you Mike! Excellent video! Learnt a lot. I just had one small doubt. For the Copy Assignment Operator Overload do we really need a return type of Array reference object? Since the copy assignment operator overload function is a member function it has access to the private member pointer *data. So it can very well copy the values from rhs object into the this objects data pointer. So we can code the function like so as well: void operator=(const Array& other) {
    std::cout

    • @MikeShah
      @MikeShah  3 месяца назад +1

      Indeed, the return type in the provided example does not make a difference to the copy taking place. I believe however, if you want to chain together expressions, you need a return value.
      e.g.
      A = B = C // having a 'void' in here will break the type system.
      (A = B).callFunc(); // Though I probably would not recommend writing code this way anyway.
      So perhaps if you want the ultimate flexibility in your code (so you can chain) return the type, otherwise if you want to disallow chaining, use 'void' -- which in some way, actually indeed seems preferable :)

    • @dwivedys
      @dwivedys 3 месяца назад

      Thank you for taking the time out to reply to my comment! Means a lot and please do continue making the awesome videos you make! God bless you 🙏

    • @MikeShah
      @MikeShah  3 месяца назад +1

      Cheers! ​@@dwivedys