4 ms·
I 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
by planede 4y ago
I 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.