... And if a modern C++ app is supposed to use smart pointers, how is that more efficient that C# references? I thought the lesson learned by the designers of the GC was that reference counting was slower than garbage collecting.
I believe that needs to be put in the right context. Garbage collection can be more performant than reference counting, so if you are designing a language that relies heavily on managed memory, a GC is the way to go. But there's the rub... C++ offers you options that allow you to express your code without using reference counting at all, possibly at the expense of memory safety.
Take for instance an object that is not meant to survive the scope it's allocated in. Assuming it's a reference type, in C# it gets invariably allocated on the managed heap and you incur collection costs. In C++, you could use a unique_ptr, or even just allocate it on the stack. Sure, that's not foolproof, but the gains in performance and memory pressure are significant.
That's where a smarter compiler could really help: in C++ it could be more aggressive in detecting dangerous situations; in C#, it could detect cases in which the lifetime of an object can be safely determined at compile time and get them out of the hair of the GC (and possibly onto the stack).
This is just the tip of the iceberg, but I already rambled enough.