4 ms·
Hmm, not sure I'd trust this. I took a look at the shared_ptr page and didn't see it mention reference cycles or weak_ptr https://cppbyexample.com/what_is_shar
by scaredginger 4y ago
Hmm, not sure I'd trust this. I took a look at the shared_ptr page and didn't see it mention reference cycles or weak_ptr
https://cppbyexample.com/what_is_shared_ptr.html https://cppbyexample.com/what_is_shared_ptr.html
- MauranKilom 4y agoThe site is very clearly not a complete guide, and has to leave out 90% of what a competent C++ programmer should know about any given topic (in order to remain accessible). I mean, the word "undefined" only appears in two of the examples. But I'd say it doesn't teach any bad (or outdated) habits, which is a big step up from most tutorials/articles/SO answers.
- scaredginger 4y agoYeah idk, I prefer when C++ teaching resources tell the reader where the bodies are buried. I couldn't give this to juniors and trust them not to leak memory Agree balancing accessibility and comprehensiveness is difficult though. I could see an argument for leaving shared ptr out of this guide if they think cyclic referencing is too advanced, and I can also see the argument that without knowing shared ptr exists, the user may write hacks much worse to get around the problem
- planede 4y agoI have an other gripe with that page: > [about std::make_shared] This function is useful because objects might throw exceptions during construction and if they do we still need to call delete on the pointer we received from new otherwise we will leak the pointer. This is oversimplified and just plain incorrect. There was never a possibility that a statement like `auto sh_ptr = shared_ptr<Widget>(new Widget);` could leak. However possibility for leak existed for calls like `foo(shared_ptr<Widget>(new Widget), shared_ptr<Widget>(new Widget))`, because evaluation of function arguments were unsequenced. This hole was fixed in the language in C++17, where function arguments became indeterminately sequenced. And possible advantage for `make_shared` is the shared allocation for the control block and the object. It is not a clear advantage, as remaining `weak_ptr`s keep the whole allocation alive, even after the object itself is destroyed. But I wouldn't include this to a tutorial. One annoying place where you can't use `make_shared` and `make_unique` is for invoking private constructors, even in a context where you could use the private constructor directly (like a static factory function within the same class). Since `make_shared` and `make_unique` are typically not friends of your class, they can't call the constructor indirectly. There are some workarounds for this, but the easiest way is just to use `new` here, it's fine.
- deadbeeves 4y agoIt seems more robust to just make std::make_*() a friend function than to pepper the code with news.
- planede 4y agoI agree. If you can, just use the make_* functions. It also reduces needless repetition. For `make_*<Widget>(args...)` I need to write the type once, for `*_ptr<Widget>(new Widget)` I need to write the same type twice. Not counting cases for `Base/Derived`.
- MauranKilom 4y agoThat only works if `std::make_*` is actually where `new` is called. It could just as well be called deeper in some library implementation detail like `std::__gnu_cxx_v3::__construct_as(...)` (made up example), in which case you're SOL.
- deadbeeves 4y agoHmm... Good point. I don't think it's a portable solution.
- account42 4y agoIt also would allow anyone to construct your class via make_* which kind of defeats the point of making the constructor private in the first place.