Tags C & C++
C++ is a difficult language. I have a few years of experience with it, and still there are a lot of things I don't know. The more I learn, the more I come to realize that it's very hard to become a C++ guru. The distance between a beginner (someone after an introductory C++ book or a Uni class) and an expert is huge.

One of the most problematic issues in C and C++ is pointers. There's a known quote saying that "There are two kinds of programmers - those who understand pointers, and those who don't". Pointers are dangerous and error-prone. Most of the toughest bugs C/C++ programmers face are pointer related.

Hence, expert C++ programmers try to avoid "bare" pointers (T* pt = &t...) as much as possible. And in most cases, they suceed:

  • References elegantly solve the problem of "passing arguments by reference" (rather than by value). There's no more need to pass a pointer to a function in order to avoid passing "heavy" objects, or to enable value return through this pointer. Const and non-const references can be used for this purpose, much more safely.
  • Constructors and destructors allow encapsulation of pointer members of classes, creating and deleting them in a controlled, safe way.
  • The excellent "string" class from the STL takes care of the endless char* games C programmers tend to play so much.
  • STL containers leave almost no reason to build complicated, linked (and hence error-prone) data structures.
  • STL iterators encapsulate pointer-based traversal of these data structures.

And indeed, I find myself using pointers less and less, the more experienced I become. Even when I use them, I try to safely "lock" them in classes.

But avoiding pointers is not always possible. For instance, containers of pointers are sometimes useful (e.g. to implement polymorphic behavior by holding a container of different objects, implemented with pointers to derived classes). Another issue is exception safety. If some function allocates a pointer and fiddles with it, releasing it in the end, it is apt to encounter memory leak problems in case of thrown exceptions. If some called function/operator/whatever throws an exception in the middle, the pointer will not be deallocated, and if the exception is non-fatal, a memory leak will occur.

Therefore, lately I'm trying to make sense, that is to *really* make sense of smart pointers. Templated smart pointers allow encapsulating pointers to any kind of object. But the issue is far from simple, since there are many "object ownership" models people use pointers for. Identifying and safely implementing these modules is difficult.

For instance, the popular (and maybe the soon to become standard) Boost library has an implementation of smart pointers. It consists of no less than 6 classes (4 smart pointers and 2 smart arrays). Just understanding the difference between the classes and knowing when to use each one requires deep C++ knowledge and a lot of experience.

I'm digging in Boost's docs, Alexandrescu's Modern C++ design, and Meyers' More Effective C++, each containting a lot of smart pointer info, plus a few websites. Hope I will have good news to report...


Comments

comments powered by Disqus