The JVM and CLR environments don't use reference-counted garbage collection |
What you're saying here is a bit intrinsic, but C# and Java references are reference counted storage in C# and Java. What you're talking about is the garbage collection phase, which is an internal issue for C# and Java programmers. The only way there can be any realization that an instance has been released is for the reference count to reach zero, which is where garbage collection finally comes into play for release of memory. Prior to that, at most, the instance might be relocated, but not released.
The point you are making is that in std::shared_ptr there can be circular references which cause memory leaks (creating such a cycle means nothing ends up releasing).
For the students here, that means A refers to B, while B refers to A through smart pointers. When that can happen, user code might release both A and B, but since they "hold" references to each other, nothing will be deleted.
The std::shared_ptr relies upon std::weak_ptr to break this cyclic reference (Scott Meyers has other important recommendations), but that only occurs if the user happens to create the situation (for all languages). Fortunately it isn't all that typical. Unfortunately, naive developers hardly ever realize when it has happened.
C# and Java track this to break these cycles, but fundamentally the references ARE counted. The OP is not at a level where such differences actually matter. A debate on the subject is a little beyond the scope here, and garbage collection wasn't really part of the substance - automatic resource release using RAII (which wasn't brought up either) was the primary point.
By "both environments" one must clarify that you're referring to C# and Java, not C++. Garbage collection in C++ is either implemented through a library (rare), or in an forthcoming version of C++, when/if they get around to it.