If you pass a unique_ptr it has to have redirection through a pointer, so it isn't quite zero cost.
However, since the entire point of using a smart pointer is to control the ownership I'm not that bothered.
It has a null check on destructor (and a delete of course), which is good enough for "zero cost" to me
I guess it is more complicated than i thought, but i think it is fair to compare them pointers too. Because most of the time you will probably need to store it as a pointer
At any rate, the definition of “zero cost” isn’t “it’s the same as a raw pointer”. Rather, it should be read as “its cost is the same as the equivalent functionality rolled by hand”. Shared_ptr implements a ref counting mechanism, which, absent a real GC, is necessary for actual shared ownership.
That's why shared_ptr has horrible performance, the spec requires that the control block is thread-safe. Perf tanks due to the atomic load/stores. If you roll your own with a standard load/store you'll see significant performance increase which means it's definitely not zero-cost.
This is why Rust explicitly went with Arc/Rc[2] so you don't have to pay that cost(although ambiguous ownership I would argue is a pattern you should try to eliminate anyway).
[1] https://en.cppreference.com/w/cpp/memory/shared_ptr
[2] https://doc.rust-lang.org/std/rc/struct.Rc.html / https://doc.rust-lang.org/std/sync/struct.Arc.html
It is true that the ref count is kept atomically, which allows accessing two distinct shared pointers that happen to point to the same object from different threads. This is pretty much a requirement to support the baseline distinct object thread safety (aka "as safe as int), but it is not what the unqualified "thread safe" normally refers to.
/pedantic
Anyway, it is true that with shared_ptr sometimes you might end up paying for what you do not use, but doing otherwise would have made any use of shared_ptr in threaded applications extremely unsafe so it was felt that in this case the cost was worth it for a vocabulary type object.
What kind of definition is that? Zero cost is exactly that - 0 cost, the same performance as if you were not using the abstraction. The alternative to an abstraction is not "my hand-rolled implementation of said abstraction" - it is not using the abstraction, at all (but using lower-level mechanisms to achieve the same goal). 0-cost is used to tell people "you will still achieve the same performance by using the abstraction - and you gain additional benefits (safety, readability etc)". If I can get better performance with raw pointers, then smart pointers are not zero cost (it's still a good idea to use them instead of raw pointers! Just, let's stop pretending they are zero-cost)
Most of the abstractions (E.g. iterations) are zero cost as opposed to additional functionality like shared pointers or resizable vectors.
i.e. there is no way to end up with faster code that does the same thing, without using the abstraction.
This is the very definition of zero cost abstractions.