CppCon 2019: Arthur O'Dwyer “Back to Basics: Smart Pointers”

Поділитися
Вставка
  • Опубліковано 26 сер 2024
  • CppCon.org
    -
    Discussion & Comments: / cpp
    -
    Presentation Slides, PDFs, Source Code and other presenter materials are available at: github.com/Cpp...
    -
    Smart pointers are one of the key features of modern C++. We'll cover the two fundamental strategies used by the standard smart pointers: unique ownership transfer and reference-counting. We'll show how shared_ptr uses control blocks to implement reference-counting of arbitrary objects, and how to use weak_ptr in conjunction with shared_ptr. We'll explain the convenience functions make_shared and make_unique, and demonstrate how they are more than just conveniences. Finally, we'll motivate, implement, and demystify the curiously recurring template enable_shared_from_this<T>.
    Attendees will leave this session with a clear understanding of how C++11's smart pointers work under the hood.
    -
    Arthur O'Dwyer
    New York
    Arthur O'Dwyer is the author of "Colossal Cave: The Board Game," "Mastering the C++17 STL" (the book), and "The STL From Scratch" (the training course). He runs professional C++ training courses, is occasionally active on the C++ Standards Committee, and has a blog mostly about C++.
    -
    Videos Filmed & Edited by Bash Films: www.BashFilms.com
    *-----*
    Register Now For CppCon 2022: cppcon.org/reg...
    *-----*

КОМЕНТАРІ • 57

  • @LordShadow144
    @LordShadow144 3 роки тому +29

    2:13 "auto putter", "unique putter", "shared putter", "weak pointer"

  • @frikbrits6335
    @frikbrits6335 4 роки тому +29

    Just had to smile at the "putter" 's. But still hugely informative talk.

  • @ArpitAgarwal1
    @ArpitAgarwal1 3 місяці тому

    Your talks are very clear. Thanks for educating a new generation of CPP users.

  • @samhughes1747
    @samhughes1747 Рік тому

    "I'd have trouble pointing at something and saying, 'Yes, this is a good example!'" This is such a relatable comment!

  • @sofasurfer3793
    @sofasurfer3793 3 роки тому +8

    The pubsub pattern is a good motivation for weak_ptr. The point of the pattern is to decouple publishers and subscribers. So publishers need to keep a list of subscribers, but that list should contain weak_ptr's so the subscribers arent forced into living longer than they're supposed to.
    As a rule, if you store a pointer to an object, then either (A) you're responsible for keeping it alive and you should use a shared_ptr, or (B) it's not your job to keep it alive and you should use a weak_ptr and gracefully handle the case when it's not there.

  • @stephenjames2951
    @stephenjames2951 4 роки тому +14

    Enjoyable review of smart pointers.

  • @Skeksis0
    @Skeksis0 3 роки тому +5

    At 45:45 - shared_from_this can only be called on a previously shared object. assert(p->shared_from_this() == nullptr) will throw a std::bad_weak_ptr since C++17, and is undefined behaviour on older standards.

    • @robertzimmermann9710
      @robertzimmermann9710 2 роки тому +1

      Well spotted! In general, I still have a mixed feeling about the whole (current) shared_from_this scheme, at least for inner usage within the according classes. It actually implies, that classes, that derive from std::enable_shared_from_this, should always be instantiated via an (authentification) factory pattern, that solely produces shared pointers of this class and other construction path ways should be prohibited. This might be not that problematic for single non further derived classes since the user of the class sees the enable_shared_from_this and can deduce the required usage context accordingly. But with further derivation, things can quickly become nasty.

  • @rrw00
    @rrw00 4 роки тому +13

    I can see a lot of hard work went into that beard. Oh, and the talk was good.

  • @kamilziemian995
    @kamilziemian995 Рік тому

    Very good presentation. My knowledge about smart pointers is much better after watching it.

  • @guppiefang
    @guppiefang Рік тому +2

    Around 50:30, that Listener object that uses `shared_from_this()`, seems like a memory leak. The shared pointer will be stored in the lambda that is presumably stored in some internal list, waiting for connections, so now if you drop all shared_ptrs to the Listener, it will not deallocate. No? Am I imagining that incorrectly? I thought he was going to store a weak_ptr as part of the lambda for this reason.

  • @johnjones8330
    @johnjones8330 4 роки тому +12

    This talk could have better covered the difference between an owning and a non-owning raw pointer and the place for using non-owning raw pointers in conjunction with smart pointers (with no owning raw pointers)...

    • @AM-qx3bq
      @AM-qx3bq 4 роки тому

      I heard that there were still valid use cases of raw over smart pointers, as non-owning references to shared data, however I can't find a talk where this is highlighted :/

    • @shadokugel
      @shadokugel 4 роки тому +2

      @@AM-qx3bq If you are still interested, e.g. Herb Sutter talked about this: ua-cam.com/video/xnqTKD8uD64/v-deo.html
      Also here: ua-cam.com/video/hEx5DNLWGgA/v-deo.html

    • @jvsnyc
      @jvsnyc 3 роки тому

      I beat that point to death in my comment. Obviously, I agree.

  • @yuehuajia3176
    @yuehuajia3176 4 роки тому +2

    Great talk by Arthur.

  • @liloolo
    @liloolo Рік тому

    Great video!

  • @anatmiller8193
    @anatmiller8193 2 роки тому +1

    Great Lecture! thank you

    • @CppCon
      @CppCon  2 роки тому

      You are welcome!

    • @CppCon
      @CppCon  2 роки тому

      You are welcome!

  • @amadlover
    @amadlover 4 роки тому +1

    Very informative. Thanks

  • @wizardy6267
    @wizardy6267 3 роки тому +2

    Nice talk :) "enabled_shared_from_this" is a really long class name, would it be better to just call that "shared_this"?

  • @rahuldeshmukhpatil
    @rahuldeshmukhpatil 3 роки тому +1

    shared_ptr aliasing is something that must be in the talk !!!

  • @pajeetsingh
    @pajeetsingh 3 роки тому +2

    "I use plain old C* with lots of fragmented memory because I am competent" - Linus

  • @masheroz
    @masheroz 2 роки тому

    At 42:50, what scope does sptr have?

  • @deanroddey2881
    @deanroddey2881 3 роки тому

    It's far better to have specific implementations of what I can 'janitorial' classes for things other than allocation/deallocation. Having generic unique pointer doing something like closing a file is very misleading. There's little that would tell the reader that that was going to happen. So it falls into the too clever for its own good category.
    I have a broad family of such janitorial classes in my system to do all kinds of things, and they are much more self-documenting, and generally trivial to implement so no particular burden to have a bunch of them.

    • @robertzimmermann9710
      @robertzimmermann9710 2 роки тому +1

      But you miss, that the combination of deleting the file and expressing unique ownership is of relevance here. I do not understand, what should be misleading with a using UniqueFilePtr = std::unique_ptr. One simple line explains everything you want and have to know about this class. And it's only an example for the huge benefits of unique_ptrs in contrast to raw pointer usage. This talk is not about higher level responsibility designs.

  • @qqi239z123
    @qqi239z123 2 роки тому +1

    When I pass unique_ptr by value, compiler complains that I wan to use copy constructor and it seems that compiler is right and this presentation is incorrect.

    • @pleaseexplain4396
      @pleaseexplain4396 Рік тому +1

      You need to pass it using std :: move that is why the compiler is complaining! unique_ptr's are not copyable and hence you either need to move them into the called function or pass them by reference. When using move() you are clearly indicating that you are passing the ownership of resource deletion to the callee.

    • @ramakrishnansubramanian6597
      @ramakrishnansubramanian6597 2 місяці тому

      It was confusing to me too. Using std::move wasn't all that obvious when "passing by value''

  • @jvsnyc
    @jvsnyc 3 роки тому +3

    So in a Nicolai Josuttis talk from the same year, he explains what an absolute disaster for performance you can have in a heavily multi-threaded application if you pass shared pointers around everywhere by value in each of a bunch of different threads:
    ua-cam.com/video/XH4xIyS9B2I/v-deo.html
    This largely goes away if you pass them by reference, as they are no longer are contending to atomically increment and decrement the shared reference counter in the control block every time anyone blinks, breathes or scratches their nose.
    I think what I got from *this* talk was that these functions all calling each other shouldn't have shared pointers in their signatures in the first place, whether or not they are heavily multi-threaded.
    This talk might not have made as clear as some other talks what that means in practice for the befuddled developer -- sure, no explicit new or delete might be great (unless you need to pass in a custom deleter, perhaps) and we don't want any raw *owning* pointers, but where do unique_ptr and shared_ptr show in function signatures? If hardly ever, do we just see a .get() once and then it's raw pTurtle s all the way down?
    Lastly, different talks seem to disagree about the main use cases for weak_ptr. This talk acknowledges that circular references are a thing, but seems to think they just shouldn't exist. That sounds almost ridiculous, or like trolling, many people work primarily with data structures with all kinds of circular references in them -- we might try to say "just forget about smart pointers in this case and program those the same way you would have in 1995" but I don't think that is really the take-home message from this talk, but it does feel that way for a good bit. If you are working with data structures that do contain cycles - maybe really advanced ones like the "doubly-linked list" do we ignore smart pointers or use weak_ptr's to save our butts? I don't think there is a third option.

    • @jvsnyc
      @jvsnyc 3 роки тому +2

      This Herb Sutter talk does a lot to explain how to deal with various data structures in terms of pointer ownership. Many people have heard "use weak pointers to break cyclic dependencies" but that is sort of weak as well. I am still digesting it, he has a LOT to say, but that talk is here:
      ua-cam.com/video/JfmTagWcqoE/v-deo.html
      The difference between having some basic idea of how to use smart pointers and really understanding the best practices and how to make optimal use of them...is large.

  • @MasterOfMisc
    @MasterOfMisc 4 роки тому +7

    If your writing new and delete manually your doing it wrong! - Good talk by the way.

  • @alihsanelmas
    @alihsanelmas 4 роки тому

    42:08

  • @liberatemi9642
    @liberatemi9642 3 роки тому +2

    “Putter” - it’s not mini golf- but it is rather aggravating.

  • @nutt.rangsiman
    @nutt.rangsiman 2 роки тому

    Pointer makes C++ a fantastic OOP language.

  • @__hannibaalbarca__
    @__hannibaalbarca__ Рік тому

    It should be programmer{CS} be a good mathematician; and than we can get A Very Hi. Performance programming language _C++_

  • @KillerMZE
    @KillerMZE 4 роки тому +3

    If you don't throw exceptions, you don't need exception safety

    • @silvesterseredi4360
      @silvesterseredi4360 4 роки тому +6

      If you're talking about RAII objects, then they are useful even if you have exceptions disabled - they make it a lot harder to accidentally leak by forgetting to clean up. Applies especially if you might add a return into the middle of your function, thereby circumventing any cleanup code you might have at the end of your function (if that's your programming style)

    • @robertzimmermann9710
      @robertzimmermann9710 2 роки тому

      Define "you"! :) Your own written code or + the extra libraries (std) you are also using and that might change with the time? And subtile aspects of exception safety are even important for some std containers, see all the optimization approaches with noexcept for std::vector...

  • @IndellableHatesHandles
    @IndellableHatesHandles Рік тому

    Passing smart pointers by reference is a code smell? Well, I should probably take a shower, then, because my code is _stinky._

  • @vladimirkraus1438
    @vladimirkraus1438 4 роки тому +2

    I was shocked by this talk. He suggests at 14:48 to pass shared_ptr pointers by value? This is the perfect example of premature pesimization. I am always passing by const reference just like any other non-trivial type.

    • @juliean123
      @juliean123 4 роки тому +12

      If you pass shared_ptr to a lot of functions, you are right from a performance standpoint. But why would you do that? Functions that do not aquire ownership should take a raw-pointer.
      In case you aquire additional ownership, passing by value is perfecly fine - if you store the shared_ptr, you copy it anyways, so passing by value at least allows moves on the callers side.
      So passing by const shared_ptr& is really non-sensical (in most cases), if you have a function that doesn't increment the ref counter, then passing in a const shared_ptr& doesn't increase safety over a raw pointer.

    • @vladimirkraus1438
      @vladimirkraus1438 4 роки тому

      @@juliean123 if you pass by value into a function and than store it (usually as a member variable of an object), then you make two copies and then immediately delete one, this means two increments and one decrement of ref count. or am I wrong?

    • @silvesterseredi4360
      @silvesterseredi4360 4 роки тому +7

      @@vladimirkraus1438 you are right about the ref counts w.r.t performance. however if you're passing shared_ptr by reference, it's possible that by the time you actually store the shared_ptr somewhere, the refcount has already dropped to zero (e.g. due to another thread or even within your call, if your code is convoluted enough) which means the control block in your shared_ptr reference is pointing to something that has already been destroyed. this leads to the counter-intuitive situation where you're using shared_ptrs diligently and still end up pointing to invalid memory. so either pass by value if you intend to potentially add another owner or pass the inner non-owning refrence/pointer if not.

    • @-taz-
      @-taz- 4 роки тому +1

      If you are passing around a bunch of shared pointers, consider just using a global variable. :p

    • @fr4nk777
      @fr4nk777 4 роки тому +2

      @@vladimirkraus1438 use std::move into the member variable to avoid the extra copy

  • @thewisewolf3543
    @thewisewolf3543 3 роки тому

    "smart" pointers.... lol