std::unique_ptr add exactly zero overhead. None. You still have to be careful with it you know. In addition, std::unique_ptr makes your code more robust, because it forces you to understand semantics and how your possibly doing useless copies, where you should use move semantics, etc.
They way std::unique_ptr is being use is pretty much the same, so the excuses of forcing you to be more careful remains. It's just make it easier to be more careful. There are also outside situations that even if you are being extremely careful, can make your software crash. Here's a small example:
Since C++ is an exception language, you have a potential memory leak with this code:
int* p1 = new int(5);
int* p2 = new int(8);
delete p2;
delete p1;
Why? Because if the allocation to p2 fails and throws, p1 will never be destroyed. What you need to do, is surround it with catch:
int* p1 = new int(5);
int* p2 = new int(8);
delete p2;
delete p1;
int* p1 = new int();
int* p2 = nullptr;
try {
p2 = new int();
} catch(std::bad_alloc& e) {
delete p1;
}
delete p2;
delete p1;
Now this is one very basic example. In a real situation, it makes it so much more complex and complicated. Also the code becomes a giant mess of catch. Now look at how the code is with std::unique_ptr:
std::unique_ptr<int> p1 = std::make_unique<int>(5);
std::unique_ptr<int> p2 = std::make_unique<int>(8);
Well, yeah, that's all there is to be. My choice is made. It's simplifies. It doesn't mean you have done less. In fact, the reason why older software(pre-11) didn't have those problems, is because in a lot of cases, people developped their own smart pointers. Then came boost, and C++11. But all in all, smart pointers have been around for a long time, just that everyone had their own.
Using raw pointers to understand the concept and the danger of it is fine by me. In real situations, smart pointers is the way to go.