I just meant you don't need necessarily need pointers at all, since you put things directly onto the stack (or into vectors/your favourite data structure), no need for additional indirection.
(Maybe Swift offers this too, but it's certainly something C++ excels at.)
The stack doesn't remove the need for heap allocation, since the stack is only useful for things that don't escape their context. The JVM can even do escape analysis and allocated short-lived objects straight on the stack - too bad the currently implemented algorithm is fairly limited.
But anyway, for shared reads or writes between CPU cores, you need the heap. Speaking of which, usage of smart pointers is most of the times less efficient than a concurrent garbage collector if that means reference counting.
C++ excels at fine-tuning the memory access patterns, depending on use-case, which can provide a big boost in performance if you know what you're doing - whether that means stack allocation, smart reference counted pointers, object pools, or whatnot. I don't yet see anything preventing people from doing that in Rust, while getting some extra safety for the common use-cases.
I wasn't meaning to suggest that heap allocation is not useful (e.g. the vectors I mentioned are heap allocations, as I'm sure you know), just, as you say, that C++ offers fine control over memory access patterns.
However, for shared read/writes you don't need the heap: global variables work fine, as does passing around pointers into some thread's stack. (They may not be the best practice, but it's still possible.)
Smart pointers are not just reference counting, e.g. the single owner pointer types Box (in Rust) and unique_ptr (in C++). Furthermore, the majority of the cost with many reference counting implementations is the atomic instructions required for safety, if you can get away with non-atomic instructions then the reference counting probably won't look so bad. (Rust can express a reference counted pointer that is statically restricted to a single thread `Rc`, while also providing the more expensive threadsafe one `Arc`.)
Rust is designed to offer the similar power in terms of controlling memory access patterns.
Swift does offer this, though in a slightly weird way; structs (and I think arrays) are stack-allocated, classes are heap-allocated. Swift structs are more featureful than, say, C++; they mostly behave like classes, but live on the stack and are passed by value.
Please, be direct with your criticisms of me rather than just implying them.
What other commonly used languages offer pointerlessness to the same degree as C++? Rust, for sure. Not C as there are no generics, making allocations + void* and simplistic data structures like linked lists more common than necessary. Maybe D but AIUI there is some struct/class difference that forces GC allocation for classes. What else?
(Also, please read my original comment properly, I was not just talking about "stack allocation".)
I am just answering about placing data into the stack, and that is offered by all descendents of Algol/Pascal/CLU/Mesa/Modula/Ada/... family of languages.
You can place data in the stack in all of them.
Quite a few of them allow for generics, starting with CLU.
Ada also offers RAII, although a bit more verbose than C++ way of doing it.
All of them allow reference arguments, hence no need for pointers for output parameters.
RAII is totally irrelevant to this discussion, and I clearly said I was not just talking about placing data on the stack.
> All of them allow reference arguments, hence no need for pointers for output parameters.
I wasn't very clear, the use of a C-style pointer is irrelevant: if it is being used as a reference (i.e. not owning, no need for clean-up/deallocation), then it counts as a reference. I was using the Rust terminology where 'pointer' mostly refers to 'smart pointer'.
So a Swift compiler will be able to optimize away ARC calls deemed unnecessary via dataflow optimizations, which a C++ cannot apply.