MicroStation's APIs make extensive use of RefCountedPtr, and make zero use of std::shared_ptr. Since this is the MicroStation programming forum, the short, practical answer is: use RefCountedPtr where MicroStation requires it, and use whatever smart pointers you want to in your own code.
FWIW 99.9% of implementations of IRefCounted do *not* implement their own reference-counting logic; they just subclass from RefCountedBase and get that stuff for free.
std::shared_ptr can point to any type of object, and provides support for weak references via std::weak_ptr. But it pollutes APIs extensively - in order to share ownership you have to pass shared_ptr<T> all over the place, which also introduces the need for nullptr checks all over the place. Because the ref-count is external, it potentially require two allocations, and management of the ref-count is complicated by the existence of weak_ptr.
Intrusive pointers like RefCountedPtr can only point to objects which expose an internal ref-count, and do not readily support weak references. But that enormously simplifies management of the ref-count. It also allows code receiving a ref-counted object by reference to take a ref-counted ptr to that object, extending its lifetime, which can be good and bad: good, in that the API is not polluted; bad, in that if the object was allocated on the stack we're about to crash the program, which is why MicroStation's ref-counted objects tend to have private constructors and public Create() methods returning ref-counted pointers to heap memory. Also, there are corner cases in which you might want a single class to implement two interfaces, both of which derive from IRefCounted - that can never work without bringing ugly virtual inheritance into the mix.
You could argue that shared_ptr makes ownership more explicit in an API; or counter-argue that the whole point of shared ownership is you're not supposed to have to think about ownership.
FWIW 99.9% of implementations of IRefCounted do *not* implement their own reference-counting logic; they just subclass from RefCountedBase and get that stuff for free.
std::shared_ptr can point to any type of object, and provides support for weak references via std::weak_ptr. But it pollutes APIs extensively - in order to share ownership you have to pass shared_ptr<T> all over the place, which also introduces the need for nullptr checks all over the place. Because the ref-count is external, it potentially require two allocations, and management of the ref-count is complicated by the existence of weak_ptr.
Intrusive pointers like RefCountedPtr can only point to objects which expose an internal ref-count, and do not readily support weak references. But that enormously simplifies management of the ref-count. It also allows code receiving a ref-counted object by reference to take a ref-counted ptr to that object, extending its lifetime, which can be good and bad: good, in that the API is not polluted; bad, in that if the object was allocated on the stack we're about to crash the program, which is why MicroStation's ref-counted objects tend to have private constructors and public Create() methods returning ref-counted pointers to heap memory. Also, there are corner cases in which you might want a single class to implement two interfaces, both of which derive from IRefCounted - that can never work without bringing ugly virtual inheritance into the mix.
You could argue that shared_ptr makes ownership more explicit in an API; or counter-argue that the whole point of shared ownership is you're not supposed to have to think about ownership.