If you are porting Python to something else, then smart pointers are a very useful upgrade that save you from a ton of analysis that Python just did for you. Garbage collection does almost the same thing, but you need to deal with python's "with" somehow then.
We usually prefer the adjective "deterministic" over "stupid". Simplicity, zero overhead, and "user pays" are virtues.
People who complain about C++ smart pointers tend to be the ones who reflexively reach for shared_ptr. (We call that habit "Java Disease".) Most good C++ programs have zero uses of shared_ptr. Also, passing around shared_ptr or unique_ptr in public interfaces puts you in a state of sin.
If they are passed by value or move, you are doing complicated things with ownership that deserve to be encapsulated in a named type. If you are passing them by const reference, you would usually better pass a regular pointer or reference to the pointed-to type. If you are passing them by non-const reference, you have bigger problems.
In practice, the new type usually starts out as a PIMPL class with just a std::unique_ptr<impl> member. But often, once the type is named, you discover it is a good place to park more operations.