next up previous
Next: Inheritance and Overloading Up: The GNU C++ Library Previous: Abstract Data Types

Arguments, Results, and Copying

Generally, operations defined within a value-oriented approach rest on value-based arguments and results, while those from an object-oriented approach use pointers or references to new or existing objects. When applied to classes, value-passing relies on copy-construction, not reference propagation.

Designers of value-oriented classes often give in to the urge to minimize copying overhead while still conforming to value semantics. There are many techniques for doing this, for example, via internal pointers to underlying representations that are shared whenever the support procedures determine that this is possible. The original versions of many libg++ classes in fact contained reference counting and other ploys to maintain this effect. They were later removed. C++ already contains simple ways for people to obtain copy versus reference semantics. Programmers themselves are in a much better position to know when to make copies and when to use references. Hiding these matters often leads to less efficient and predictable behavior, especially for classes like Strings. In many applications, tricks like copy-on-write add more overhead than they save. In many others, explicit use by programmers of pointers to shared Strings only when desirable and possible is more effective than any automated policy. Thus, except in a few cases where copy-prevention strategies are transparent and algorithmically superior, libg++ classes maintain the convention that a copy-constructor actually makes a copy. Similar remarks hold for assignment and other operations.

Storage Management

Such decisions reflect the idea that a basic support library should provide mechanism not policy. Most libg++ classes are designed so that users who want to implement their own policies are provided with all the tools to do so. Libg++ contains several classes and utilities that facilitate development of specialized allocation and management. For example, an Obstack class supports ``mark/release'' allocation and deallocation. The MPlex class helps manage sparse tables. An optionally included version of malloc (underlying operator new) has been shown to provide superior performance than most other versions for typical C++ (and C) programs. Other classes provide mechanisms useful for very special allocation needs.

However, this stance is probably the least defensible overall design decision in all of libg++. Effective, correct, and efficient storage management in C++ is sufficiently difficult and fragile to demand a better alternative. The only general solution is to rely on automated storage management (garbage collection). If attempts to provide full, transparent garbage collection in C++ succeed, the library (or a version thereof) should be redesigned to exploit it.


next up previous
Next: Inheritance and Overloading Up: The GNU C++ Library Previous: Abstract Data Types


Doug Lea@Sun Apr 16 06:37:14 EDT 1995