6

Could someone explain to a C++ programmer most important differences between Java (and C# as well) references and shared_ptr (from Boost or from C++0x).

I more or less aware how shared_ptr is implemented. I am curious about differences in the following ares:

1) Performance. 2) Cycling. shared_ptr can be cycled (A and B hold pointers to each other). Is cycling possible in Java? 3) Anything else?

Thank you.

watson1180
  • 2,015
  • 1
  • 18
  • 24

5 Answers5

4

Performance: shared_ptr performs pretty well, but in my experience is slightly less efficient than explicit memory management, mostly because it is reference counted and the reference count has to allocated as well. How well it performs depends on a lot of factors and how well it compares to Java/C# garbage collectors can only be determined on a per use case basis (depends on language implementation among other factors).

Cycling is only possible with weak_ptr, not with two shared_ptrs. Java allows cycling without further ado; its garbage collector will break the cycles. My guess is that C# does the same.

Anything else: the object pointed to by a shared_ptr is destroyed as soon as the last reference to it goes out of scope. The destructor is called immediately. In Java, the finalizer may not be called immediately. I don't know how C# behaves on this point.

Community
  • 1
  • 1
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • 3
    Note on performance, if `make_shared` (http://www.boost.org/doc/libs/release/libs/smart_ptr/make_shared.html) is used then both the reference count and the referenced object are allocated in one block. – dalle Dec 31 '10 at 15:49
  • 1
    Arguably, the biggest performance hit with `shared_ptr` is the interlocked increment/decrement of the ref counter – sbk Dec 31 '10 at 17:12
  • @sbk: Why do you think that is a performance hit. It is usually implemented as a single assembly instruction (no need for a lock on hardware that supports it implicitly). – Martin York Dec 31 '10 at 18:41
  • @LokiAstari In an application I use (which is heavy on shared_ptrs), interlocked inc/dec amount to 14% of the total time. – Calvin1602 Feb 28 '12 at 09:28
  • @larsmans : In C# the object is not destroyed immediately either. But you can force this with `using`. – Calvin1602 Feb 28 '12 at 09:30
3

The key difference is that when the shared pointer's use count goes to zero, the object it points to is destroyed (destructor is called and object is deallocated), immediately. In Java and C# the deallocation of the object is postponed until the Garbage Collector chooses to deallocate the object (i.e., it is non-deterministic).

With regard to cycles, I am not sure I understand what you mean. It is quite common in Java and C# to have two objects that contain member fields that refer to each other, thus creating a cycle. For example a car and an engine - the car refers to the engine via an engine field and the engine can refer to its car via a car field.

Michael Goldshteyn
  • 71,784
  • 24
  • 131
  • 181
  • 1
    There are no "normal" destructors in C# and Java, they only have finilizers, which are considered a misfeature in those languages. Destructors and garbage collection are at odds. GC basically means: no destruction, or infinite object life time. – Gene Bushuyev Dec 31 '10 at 15:31
  • There is a difference between the notion of a destructor, as in a function, being called and the destruction of an object, as in its deallocation. I know this can often get confusing because the same terminology is used for both of these events, so perhaps object deallocation would be a better choice of words to refer to the later event. – Michael Goldshteyn Dec 31 '10 at 15:36
  • 4
    destruction is not deallocation, they are very different concepts and shouldn't be used interchangeably. – Gene Bushuyev Dec 31 '10 at 15:39
2

Nobody pointed the possibility of moving the object by the memory manager in managed memory. So in C# there are no simple references/pointers, they work like IDs describing object which is returned by the manager.
In C++ you can't achieve this with shared_ptr, because the object stays in the same location after it has been created.

SOReader
  • 5,697
  • 5
  • 31
  • 53
1

Cyclical references with C++ reference-counted pointers will not be disposed. You can use weak pointers to work around this. Cyclical references in Java or C# may be disposed, when the garbage collector feels like it.

When the count in a C++ reference-counted pointer drops to zero, the destructor is called. When a Java object is no longer reachable, its finalizer may not be called promptly or ever. Therefore, for objects which require explicit disposal of external resources, some form of explicit call is required.

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
1

First of all, Java/C# have only pointers, not references, though they call them that way. Reference is a unique C++ feature. Garbage collection in Java/C# basically means infinite life-time. shared_ptr on the other hand provides sharing and deterministic destruction, when the count goes to zero. Therefore, shared_ptr can be used to automatically manage any resources, not just memory allocation. In a sense (just like any RAII design) it turns pointer semantics into more powerful value semantics.

Gene Bushuyev
  • 5,512
  • 20
  • 19
  • 4
    The C++ distinction between "pointer" and "reference" is quite specific to that language. C#/Java references are somewhere in between the two, as you can't do pointer arithmetic on them. – Fred Foo Dec 31 '10 at 15:43
  • @larsmans, The thing is that Java, semantically, not only has pointers, but it has only pointers. It is lacking a reference mechanism which guarantees that the reference is never null. But it indeed has no pointer arithmetics, and the superficial syntactic notation is not the usual pointer notation. – Gene Bushuyev Dec 31 '10 at 15:55
  • but what you're saying is misleading because it assumes the C++ definition of what a "reference" is. Java has references because they're called references. They just don't behave like C++ references. – jalf Dec 31 '10 at 16:03
  • 1
    The trouble is the two different languages have different meanings for the same word. Its meaning is specific to the context of the language (unfortunately junior developers don't get this and think that the same word means the same thing when they switch languages). I think Gene is on the correct track he just needs to re-word the answer slightly. Look at the meaning of local in different language (a local variable in C/C++/Java/C# is relatively similar switch to perl and local takes on a whole new meaning in this context). – Martin York Dec 31 '10 at 18:47