First off, let's dispel this notion that Java does and C++ does not have garbage collection. Both of those statements are false under most interpretations of the words Java, does, C++, does not, and garbage collection.
C++ does have a memory management strategy as well as support for various collection semantics. JVMs do have optimizations and alternate strategies that remove garbage collection when the scope of an object is known and would therefore not break language definition to remove.
There are many memory management strategies in common use. Some of them are well regarded by the people that use them. Other strategies should probably be avoided. What makes a memory strategy good or bad?
Before going on, let's set a benchmark which we will compare all of our strategies against. Imagine allocating memory but never releasing any of it. This would be a very correct strategy if we had infinite memory, however it clearly has poor space efficiency. We will call this strategy mass incarceration because memory is never freed.
To refine your original statement, I would agree with you to say that Java has better support for garbage collection than C++.
To support our statement, let's dive into the C++ memory model and find some bad™ things. Let's narrow our focus to mixed stack allocation + reference counting with smart pointers because it is common and exhibits typical strengths and weaknesses associated with C++ memory management. To show that this improves on the baseline, we can observe that memory is released and most programs using this (in absence of other bugs) do not leak memory.
For efficiency, C++ is hard to beat. This is not to say that the strategy does not have room for improvement, but it is a very good benchmark to compare other strategies to. This C++ model is the golden standard for performance. For pure speed, there are still some promising alternatives in the form of opportunistically removing garbage collection and new data structures that optimize for expected read/write time rather than for direct read/write count.
The reason for why C++ has such a bad reputation with regards to garbage collection is due to programmer difficulties. It is not so much that C++ does not have good memory management, but rather that many programmers do not use it as intended. This is where I mark C++ as failing in ease-of-implementation but also in versatility. The failings of C++ here really are caused by the language limitations: C++ does not have the concept of memory management. Memory management has been implemented in C++ and is officially sanctioned and supported by language maintainers and standard library. However, the compiler itself has only a rudimentary concept or understanding of the expected lifetime of an object. Rather than even having the concept of an object, C++ defines logical operations on types at addresses. There are operations for constructing a type, copying, and destructing, referencing, and dereferencing. Defining these operations in specific ways is sufficient to implement garbage collection when considered carefully and with great creativity. However, the concept of object is not part of the language. It is the people that have used the language to create the concept of object. This makes optimization of managed memory quite a bit more tricky, or sometimes impossible, because rather than a programmer defining in abstract what they want the program to do, C++ requires a much much more detailed explanation of how garbage collection should work. Deploying new strategies for memory management becomes dependency hell and further development becomes a challenge.
Java in contrast was built entirely around the concept of a managed object, so it is no surprise that this one concept above all else is somewhat reasonable. There have been many difficulties in getting to the impressive performance benchmarks that Java now displays. GC has been no small part of those difficulties. Even today, the stop-and-pause vs incremental nature of Java memory management makes the platform unsuitable for specific use-cases. However the language as most people know it does not require memory management from the programmer. That concept has been mostly abstracted away and unused data simply disappears out of existence. Here is my rubric:
On a 4.0 scale that would be 2.8 for Java vs 2.1 for C++. Both of those are C grades and passing but Java does better by my standard.