LinuxDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


C++ Memory Management: From Fear to Triumph, Part 3
Pages: 1, 2, 3, 4

Learn to Love C++ References

The C++ reference seems at first such an ungainly thing. Why would anyone want an alias for an existing object? Isn't it merely confusing? This skepticism of references is usually due to the way they are presented. The real place where references make a profound difference is in parameters to functions and catch clauses. Under these circumstances, references are overwhelmingly desirable, as shown in the following list.

Even when preventing modifications to objects passed to a function is an issue, a const reference can often be used instead of passing by value. A well-designed class will declare all methods that do not actually modify the state of the object as const, signifying that calling these methods on a const object is allowed. Thus, read-only operations will work on const references to objects of such classes, making pass-by-value only a rare necessity. (Remember not to return a const parameter by const reference, however.)

Now it's clear that references are a very important tool for better C++ programs. They are safe, efficient, and don't slice objects. References should be your first choice for function and method parameters. For exceptions, the rule is even more strict. Not catching an exception by reference is almost always a mistake.

Don't Sacrifice Program Correctness to Performance

C++ makes high performance possible. Indeed, this is frequently a major reason for choosing C++. Unfortunately, it is not always feasible to maximize efficiency while having the program function correctly. When that happens, program correctness must always win out over performance. In practical terms, it should not be difficult to take this approach. Only about 20 percent of a program is typically the performance bottleneck [[Mey96]], and it is important to rely on profiling tools to find that 20 percent. "Programmer's intuition" is most often wrong regarding these bottlenecks.

In general, choosing an efficient design with good algorithms, along with a straightforward implementation (usually in C++ style, as shown previously) will yield excellent performance in a C++ program. If further optimization is necessary, it should be undertaken with the aid of analytical tools.

Regarding memory management, there is a critical area where incorrect optimization leads to errors. C++ programmers, having learned the lesson about the benefits of references, are very reluctant to return objects by value from their functions and methods. The efficiency concerns are understandable: returning an object by value generates temporary objects, with their attendant construction and destruction costs. Unfortunately, references, so useful as parameters, are rarely desirable in return values. The many errors that are possible when returning objects by reference or pointer have been previously covered in the first article.

If you return dynamically allocated objects from your function, you should generally do so via a pointer. The auto_ptr is also very useful in such cases. In many situations, however, it is impossible to get around returning an object by value. Fortunately, the compiler frequently comes to your rescue [[Mey96]]. The temporary objects generated for a return-by-value can be automatically avoided by the compiler. The following code shows how you can help this process, by giving the compiler a hint. Of course, the optimization is compiler dependent, and some compilers will even do the right thing even without the hint.

Example 13. Return value optimization

//---
SimpleString return_by_value() {

  //Constructing the return value like this (as part
  //of the "return" statement) helps the compiler
  //eliminate the temporary objects associated with
  //return-by-value.
  return SimpleString("Return Value Optimization");
}
//---

While avoiding return-by-value is a worthwhile goal, be prepared for the fact that it may not be possible. In those situations, give the compiler a hint as shown in the example, and accept whatever performance hit remains. It is indeed a poor bargain to allow a memory leak or a dangling reference in order to get a boost in performance.

Memory Allocation Considered Harmful

The goto. The pointer cast. Memory allocation? Unfortunately, not all harmful things in this world can be avoided. Memory allocation is one of them. After reading this series of articles, you probably would not be surprised to learn that the majority of both C++ and C errors are related to memory. Yes, memory allocation truly is harmful.

The prescription for allocating memory is actually similar to the one for goto. You can, in fact, avoid memory allocation in the majority of your code by encapsulating memory management in its own subsystem. Operations with memory are like toxic chemicals: extremely useful if confined to a small area and put to work, but terribly destructive if allowed to leak out. This series of articles presented several techniques, such as smart pointers and allocators, that can restrict memory operations to a well-defined part of the code. Keep your memory operations bottled up, where you can use them to your benefit in relative safety, and wonderful things should happen to your program.

Memory allocation: it's harmful but good!

Series Conclusion: Every C++ Program Needs a Memory Management Design

If you remember only one thing from this article series, it is that every C++ program needs a memory management design. After all, the designers of memory-managed languages such as Java and Python have put a great deal of thought into their automated memory management schemes. In C++, this task is up to you.

If you will be developing a subsystem for a specific application rather than a general-purpose language, your approach to memory management can be much simpler and much more focused. Nevertheless, you will need an approach. Ad-hoc calls to new all over your program will just leave you chasing memory leaks and dangling references, which is a thankless task that quickly becomes impossible as the program grows. A sound memory management design, on the other hand, will allow you to fine-tune your code safely, in ways not possible with a memory-managed language. This is the key to effective use of C++.

Further Reading

This information appears in the previous two articles. It is included again for your convenience. A number of very useful resources are available regarding C++. Notes on these resources are provided here (the Bibliography itself follows).

First, you need a book with broad coverage, which can serve as an introduction, a reference, and for review. Ira Pohl's C++ by Dissection [[Poh02]] (for which the author of this article was a reviewer) is an example of such a book. It features a particularly gentle ramp-up into working with the language.

In addition to a book with broad coverage, you will need books that focus specifically on the most difficult aspects of the language, and present techniques to deal with them. Three titles that you should find very valuable are Effective C++ [[Mey98]], More Effective C++ [[Mey96]] (both by Scott Meyers) and C++ FAQs [[Cli95]] (by Marshall P. Cline and Greg A. Lomow). There is also an online version of the last title.

The key to reading all three books is not to panic. They contain a great deal of difficult technical details, and are broken up into a large number of very specific topics. Unless you are merely reviewing material with which you are already familiar, reading any of these books from cover to cover is unlikely to be useful.

A good strategy is to allocate a little time (even as short as 15 minutes) each day to work with any one of the Meyers' books, or with C++ FAQs. Begin your session by looking over the entire table of contents, which in all three books has a very detailed listing of all the items covered. Don't ignore this important step; it will take you progressively less time as you become familiar with each particular book.

Next, try to read the items that are most relevant to the current problem that you are trying to solve, ones where you feel that you are weak, or even those that seem most interesting to you. An item that looks completely unfamiliar is also a good candidate it is likely an important aspect of C++ that you are not yet aware of.

Finally, when you want insights into bureaucracy, tips on what to do with your icewater during NASA meetings (answer: dip booster rocket O-ring material into it), or just a good laugh when you are frustrated with C++, try Richard P. Feynman's "What Do You Care What Other People Think?" [[Fey88]]. The second article in this series describes why Feynman's book is so important.

Bibliography

This bibliography also appears in the previous two articles of this series. Notes on the bibliography are given in Further Reading.

[Cli95] Marshall P Cline and Greg A Lomow. C++ FAQs. Frequently Asked Questions. Addison-Wesley Publishing Co., Inc.. Copyright 1995. 0-201-58958-3.

[Fey88] Richard Feynman and Ralph Leighton. "What Do You Care What Other People Think?". Further Adventures of a Curious Character. W.W. Norton & Company, Inc.. Copyright 1998 Gweneth Feynman and Ralph Leighton. 0-393-02659-0.

[Mey96] Scott Meyers. More Effective C++. 35 New Ways to Improve Your Programs and Designs. Addison-Wesley Longman, Inc.. Copyright 1996. 020163371X.

[Mey98] Scott Meyers. Effective C++. 50 Specific Ways to Improve Your Programs and Designs. Second. Addison-Wesley. Copyright 1998. 0-201-92488-9.

[Poh02] Ira Pohl. C++ by Dissection. The Essentials of C++ Programming. Addison-Wesley. Copyright 2002. 0-201-74396-5.

George Belotsky is a software architect who has done extensive work on high-performance internet servers, as well as hard real-time and embedded systems.


Return to the Linux DevCenter.




Linux Online Certification

Linux/Unix System Administration Certificate Series
Linux/Unix System Administration Certificate Series — This course series targets both beginning and intermediate Linux/Unix users who want to acquire advanced system administration skills, and to back those skills up with a Certificate from the University of Illinois Office of Continuing Education.

Enroll today!


Linux Resources
  • Linux Online
  • The Linux FAQ
  • linux.java.net
  • Linux Kernel Archives
  • Kernel Traffic
  • DistroWatch.com


  • Sponsored by: