I'm going to ignore the broader C++ issue that the language has holes in it that let you hide pointers inside of non-pointer-like things. Yes, many of these are UB, but there are APIs that basically require these schenanigans. Such things make automatic GC impossible from a practical perspective. Instead, we'll assume the compiler has a perfect way to instrument pointers to do this. So I'll focus on the more obvious issues:
Backwards compatibility and performance.
Let's assume you can do this while solving the C/C++ interop problem (ie: your C++ pointers still need to be the same size and store the same information as C pointers). Even so, most people don't write their code expecting garbage collection. You have decades of code out there written to destroy objects after their creation.
So what would a GC-based C++ do with such code? If it sees a pointer to an object outlive an explicit deallocation of the object, when should it be destroyed? When the user said to do it, or when the last pointer goes away? If you pick the former answer, then you haven't gained anything, since you just broke GC. And if you pick the latter, then you've broken your covenant with the user, since the user explicitly said "destroy this object and free this memory" and you didn't.
So a codebase has to be written expecting GC; you can't just give it to them behind the scenes.
Also, a common philosophy of C++ is "pay only for what you use". Garbage collection is not free. Even lifetime-scope-based GC isn't free, especially of the shared_ptr
variety. But you're forcing this cost on everyone even if they didn't ask for it and don't need it.
Not having automatic memory management is a feature of C++, not a bug. It allows users to have the freedom to decide for themselves what the best form of memory management will be.