Shared pointers are only really supposed to be used for sharing ownership across threads, where it's impossible to know who is the last user of a resource and so you have to share the ownership.
There are other scenarios which need that sort of thing. The key factor isn't whether threads are in use, but rather whether the lifetime of the object can be tied at compile time to a particular scope. Threads aren't the only way in which that can become … well, complicated to determine. A classic example is with an implementation of an interpreted language: the lifetime of an object is often determined by a scope, but not a scope in C++ but rather in the other language.
Simplistic rules are for noobs. We're not noobs round here.