Note: Most of this page is about pointer management in CeePlusPlus.
. See also ClassesWithoutOo
You have CeePlusPlus
as your first ObjectOrientedLanguage
. You get so sick of trying to handle object references without GarbageCollection
that you end up making many classes into Singletons. Then you discover that singletons, being not-very-cleverly-disguised globals, make the code hard to refactor. Later you discover ReferenceCounting
("smart") pointers and spend a week building and testing a SmartPointer
template [this being pre-STL]. You think you're home free, but then you get caught by circular references. Finally, you find a language that has real GC and stuff C++ away in a closet. -- WayneConrad
has no ReferenceCounting
or list-based SmartPointer
is merely an ownership passing pointer. It's only good for locals to do automatic cleanup and to protect you from exceptions. If you use an auto_ptr as a member variable, you're asking for pain.
Note that making every module a singleton reduces the modularization to CeeLanguage
-style file modules, which certainly was workable beforehand, if not the best practice. What did you forget since then?
Besides, why aren't you using the constructor and destructor properly? CeePlusPlus
doesn't need magic GarbageCollector
threads to do its dirty work. You know exactly at what point objects will be destroyed and you can easily clean up. Resource leaks aren't as common as non-C++ people assume they are. Ohhhh yes they are. My own experience is that *every* commercial project whose primary language is C or C++, as it tends toward its (desired) release date, is entirely dominated by finding and fixing memory management bugs. Eventually, the team sets a threshold of pain, and will ship knowing that memory management bugs exist, but are hit "rarely enough". -- ArlieDavis
Moreover, even so-called GarbageCollected
languages have ResourceLeak
s, if not memory leaks. Any operation that needs to be balanced will fail. So, no magic bullet there. Indeed, with CeePlusPlus
using the constructor/destructor to balance actions automatically is a common idiom and one that I sorely miss in JavaLanguage
And let's not forget that GarbageCollector
s lure you into a false sense of security where you may fail to clear references to objects, or let references hang while a thread is busy. This causes memory leaks. Indeed, if you lose control of references in a non-garbage-collected language, you only leak one node, whereas in a GarbageCollected
language, you lose the entire subgraph rooted at that node.
s only permit you to lose track of the nodes; you still have to keep track of the edges. There's an article on this in DrDobbsJournal
Feb2000, if you're interested. -- SunirShah
Actually, STL doesn't have an auto_ptr
class either. The AutoPtr
class (a SmartPointer
semantics) is part of the CeePlusPlus
"Standard Library" - which is very different from Stepanov's "StandardTemplateLibrary
". Of course, much, but not all
of STL was added to the existing CeePlusPlus
"Standard Library". For what it's worth, at one time the "Standard Library" was considering a template class named counted_ptr
. This had a similar interface to auto_ptr
but used "shared-owner" instead of "exclusive-owner" semantics. Since it was not added, most programmers have rolled their own counted_ptr
that looks (but does not act) like auto_ptr
. -- RobertDiFalco
[See also CppCountedPointerImplementation
I thought there was a reference-counted pointer in STL - I jumped to JavaLanguage
before STL became big; that's my excuse for not knowing. Thanks for setting me straight.
What I'm really talking about here is spending over half my time at the computer dealing with CeePlusPlus
pointers - making sure that things are freed in the destructor (and did I remember to make the destructor virtual), making sure that pointers are set to null or otherwise initialized in the constructor, making sure that the right thing is done with pointers when the object is assigned to, trying to figure out which of the 4 objects holding a pointer 'owns' the pointer and is therefore responsible for freeing its memory, spending late nights at the terminal trying to figure out which of the above I screwed up, causing an abend at some point far, far away from where the actual programming error was made. Sunir, it's not that I couldn't do it right - I got pretty good at it - it's that I started to resent how much time it was taking to do it right, time that should have been spent solving the customer's
problems, not the language's
problems. -- WayneConrad
All languages have trade-offs. There is a lot in CeePlusPlus
that is clearly easier to do than in the JavaLanguage
and vice versa. A good example is that unpredictable monstrosity called finalize
for releasing resources or the inability to make an instance of an immutable class, constant by modifier. There are no universal truths in software development, each tool has its place--and it's here that Sunir and Wayne go off course trying to pit one against the other, as if they aren't apples and oranges. One cannot discount a GarbageCollected
language any more than a non-garbage collected language, any more than I type safe, dynamically-bound, or statically-bound language. And, for what it's worth, there are many packages that provide GarbageCollection
. Of course, if you are doing all this to CeePlusPlus
, it probably isn't the appropriate language choice for the job--i.e. just use a higher-level language.
However, I think if the subject is ProducingSingletonGarbage
, then the above example isn't a good one. I don't think I even agree with the moniker. Personally, I would do something more language-neutral and rename the OO AntiPattern
to something like UsingSingletonToHideGlobalData
where, in any
O-O language, one uses the SingletonPattern
as a global lexical scope instead of a way to enforce a single instance of some class. As you know, there are many pages here on Wiki that criticize this use of the SingletonPattern
to dress up the use of Globals. -- RobertDiFalco
By the way, I seem to have gotten away from my original point and into an anti-CeePlusPlus rant. I was saying that overuse of SingletonPattern was a mistake I fell into, and if we can confirm that others have fallen into that same mistake, then it can qualify as one of the ClassicOoAntiPatterns.
In the LispLanguage
world, the standard idiom to manage your resources is to have a macro, say WITH-SOME-RESOURCE, used thusly:
(with-some-resource (resource parameters)
and the macro ensures that the resource is released when execution leaves its body (via an UNWIND-PROTECT). We do this with locks, databases, file-handles, etc. Simple, elegant, and correct. I thought I'd miss CeePlusPlus
's destructors, but I was way
wrong. -- AlainPicard
On the subject of finalizers and managing resources that the GarbageCollection
doesn't know about, see also ResourceAcquisitionIsInitialization
, and ReleasingResourcesInJava
. UNWIND-PROTECT is more or less try/finally with no catch - but without macros it remains tedious to do it properly.
uses the "with-some-resource" idiom with blocks. In Ruby, a resource class provides a class-method that takes a block. This method allocates a resource object, passes the object to the block, and then releases the object after control has returned from the block. Classes often overload their instantiator methods to return a new object if called without a block, or to use the "with-some-resource" idiom if called with a block. E.g.
# Allocate and return a file object:
file = File.open( "some_file.txt", "r" )
# Allocate a file, pass it to the block, close the file after the block
File.open( "some_file.txt", "r" ) do |file|
process( file )
The semantics of ref-counted pointers can be complicated, which is why the standard library doesn't include one. There's one (more than one, actually) in the fabulous BoostLibraries
's Loki library has some (very neat) ones too, see ModernCeePlusPlusDesign
has the best of both worlds when it comes to resource management, imo, since it has both GC (which you can easily sidestep if you need to, like when you need to pass a pointer to a C library) and
automatic objects you can use for RAIA. D is very much like "A better C++ for the people who actually like C++" and I'd be happy if it managed to get some more mind share.
See also SingletonPattern