Circular references are a problem in other languages, too. The existence of Java's java.lang.ref.WeakReference, or .NET's System.WeakReference, or Python's weakref illustrate this.
When it comes to heap or stack allocation, you may not even have a choice, depending on the language being used. At least C++ gives you the option of choosing in many cases. And C# does allow for both heap and stack allocation, by the way.
Likewise for the other issues you mentioned. Sure, they may have been a problem for some developers in the early 1990s. Things have changed. The language has evolved to offer ways of dealing with such scenarios, often in a much safer fashion. We now have rvalue references, move constructors, the explicit keyword, and other functionality at our disposal now.
It's not at all difficult these days to write high-level C++ code that's safe and robust. The best part is that it offers all this, without taking away the power to go deeper or to do more complex or riskier things, if the need arises. But in no way are you forced to do things unsafely these days.
Weak references are more for keeping things like hash keys from creating a reference than for preventing your program from segfaulting.
Object lifecycle and reference counting are two completely different things that only appear to be related. Even if you figure out your C++ auto_smart_magic pointers, you still have to decide when the object you're referring to is no longer necessary, just like you would in Python or Java.
I'm not sure what you're getting at with rvalue references and move semantics. They are quite unsafe. The language does nothing to prevent you from using a moved value after you've moved it.
Also, circular references are not a problem in managed languages the same way they are in C++. Managed languages automatically clean up cycles. C++ requires careful use of weak pointers to deal with cycles.
A quick example of where circular references are an issue in C++, but weak references aren't needed in other languages. Consider a doubly-linked list, where you remove two nodes from the middle, and those nodes are not reachable from anywhere else. Each node, however, still has a reference to the other:
X<->Y
In any system with a full GC, those nodes will get freed; in a reference counting system, those nodes will stay around forever.
But why have you designed your interface in such a way that this could happen?
A normal interface would allow you to remove one node at a time and this wouldn't occur.
A more advanced interface may allow you to remove 2 nodes, but would return a vector or a new list to ensure proper deallocation.
Don't get me wrong; you have to think with C++ and generally know what you're doing. However, you can write safe and high level C++ and I don't necessarily think thinking about your design is a bad thing.
Circular references are a problem in other languages, too. The existence of Java's java.lang.ref.WeakReference, or .NET's System.WeakReference, or Python's weakref illustrate this.
When it comes to heap or stack allocation, you may not even have a choice, depending on the language being used. At least C++ gives you the option of choosing in many cases. And C# does allow for both heap and stack allocation, by the way.
Likewise for the other issues you mentioned. Sure, they may have been a problem for some developers in the early 1990s. Things have changed. The language has evolved to offer ways of dealing with such scenarios, often in a much safer fashion. We now have rvalue references, move constructors, the explicit keyword, and other functionality at our disposal now.
It's not at all difficult these days to write high-level C++ code that's safe and robust. The best part is that it offers all this, without taking away the power to go deeper or to do more complex or riskier things, if the need arises. But in no way are you forced to do things unsafely these days.