Tips in C++

New, Constructors, and Exceptions

To write perfectly exception safe code, it's necessary to keep track of any allocated resources and to be prepared to release them if an exception occurs. This is often a straightforward process. We can either organize our code in such a way that no resource recovery is necessary or use resource handles to recover the resources automatically. In extreme situations, we can get down and dirty with try blocks or even nested try blocks, but this should be an exception, not the rule.

We do, however, have an apparent problem with the use of the new operator. The new operator actually performs two separate operations, first it calls a function named operator new to allocate some storage, and then it may invoke a constructor to turn that uninitialized storage into an object:

String *title = new String( "Bolt" );

The problem is that, if an exception occurs, we can't tell whether it was thrown by operator new or the String constructor. This matters, because if operator new succeeds and the constructor throws an exception, we should probably call operator delete on the allocated (but uninitialized) storage. If operator new was the function that threw the exception, no memory was allocated and we should not call operator delete.
One horrible approach is to handcraft the proper behavior by separating the allocation and initialization behavior and tossing in a try block:

String *title // allocate raw storage                                   
    = static_cast<String *>(::operator new(sizeof(String));             
try {
    new( title ) String( "Bolt" ); // placement new 
catch( ... ) {
    ::operator delete( title ); // clean up if ctor throws

So many things are wrong with this code that the approach is not worth considering. In addition to being more trouble for you, the overworked coder, it will not behave properly if String has a member operator new and operator. This is a perfect example of too-clever code that works initially but fails subtly in the future because of a remote change (for example, if someone adds String-specific memory management).
Fortunately, the compiler handles this situation for us and produces code that performs in the same way as in our hand-coded approach above, but with one exception. It will invoke the operator delete that corresponds to the operator new used to perform the allocation.

String *title = new String( "Bolt" ); // use members if present
String *title = ::new String( "Bolt" ); // use global new/delete

In particular, if the allocation uses a member operator new, then the corresponding member operator delete will be called to reclaim the storage if the String constructor throws an exception. This is yet another good reason to declare a member operator delete if you declare a member operator new.
Essentially the same situation applies to array allocation and allocations that use overloaded versions of operator new[]; the compiler will attempt to find and call the appropriate operator delete[].

Smart Pointers

Whenever we're faced with a situation that requires a feature the language doesn't support, we don't abandon C++ to flirt with some other language; we just extend C++ to support the feature in which we're interested.
For instance, it's often the case that you'll need something that behaves like a pointer, but a built-in pointer type just doesn't do the job. In those cases, a C++ programmer will use a "smart pointer."

A smart pointer is a class type that is tricked up to look and act like a pointer but that provides additional capability beyond that provided by a built-in pointer. Generally, a smart pointer uses the capabilities provided by a class's constructors, destructor, and copy operations to control access to or keep track of what it points to in a way that a built-in pointer cannot.

All smart pointers overload the -> and * operators so that they can be used with standard pointer syntax. Other smart pointers (in particular, smart pointers used as STL iterators) overload other pointer operators, like ++, --, +, -, +=, -=, and []. Smart pointers are often implemented as class templates so that they may refer to different types of objects. Here's a very simple smart pointer template that performs a check that it's not null before use:

template <typename T>
class CheckedPtr {
    explicit CheckedPtr( T *p ) : p_( p ) {}
    ~CheckedPtr() { delete p_; }
    T *operator ->() { return get(); }
    T &operator *() { return *get(); }
    T *p_; // what we're pointing to
    T *get() { // check ptr before returning it
        if( !p_ )
            throw NullCheckedPointer();
        return p_;
    CheckedPtr( const CheckedPtr & );
    CheckedPtr &operator =( const CheckedPtr & );

Use of a smart pointer should be straightforward, mimicking the use of a built-in pointer:

CheckedPtr<Shape> s( new Circle );
s->draw(); // same as (s.operator ->())->draw()

The key to this façade is the overloaded operator ->;. The -> operator must be overloaded as a member and has a rather unusual property in that it is not "consumed" when it is called. In other words, when we write s->draw(), the compiler recognizes that s is not a pointer but a class object with an overloaded operator -> (that is, that s is a smart pointer). This results in a call to the member overloaded operator, which returns (in this case) a Shape * built-in pointer. This pointer is then used to call Shape's draw function. If you write this out longhand, you'll get the following challenging expression: (s.operator ->())->draw(), which contains two uses of the -> operator, one overloaded, one built in.
Smart pointers also typically overload operator * as well as operator -> so that they may be used to refer to nonclass types.

CheckedPtr<int> ip = new int;
*ip = 12; // same as ip.operator *() = 12
(*s).draw(); // use on ptr to class, too

Smart pointers are used pervasively in C++ programming, from resource handles to STL iterators, to reference counting pointers, to wrappers around pointers to member functions, and on and on. Semper fidelis.

New Cast Operators

There's something sneaky and underhanded about old-style casts. Their syntax is such that they can often pass unnoticed in a section of code, but they can do terrible damage, like an unexpected sucker punch from a bully. Let's clarify what we mean by "old-style" cast. Obviously, the original C syntax consisting of a parenthesized type applied to an expression is an old-style cast:

char *hopeItWorks = (char *)0x00ff0000; // old-style cast

C++ introduced another way of saying the same thing with the function-style cast syntax:

typedef char *PChar;
hopeItWorks = 
    PChar( 0x00ff0000 ); // function-style/old-style cast

A function-style cast may look more civilized than its dread forebear, but it's just as nasty; avoid both of them like the plague.
Good programmers use the new cast operators because they allow you to say more precisely what you mean, and mean more accurately what you say. There are four of them, and each has a specific purpose.
The const_cast operator allows you to add or remove const and volatile type qualifiers in an expression's type:

const Person *getEmployee() { ... }
Person *anEmployee = const_cast<Person *>(getEmployee());

In this code, we've used const_cast to strip a const type qualifier from the return type of getEmployee. We could have used an old-style cast to achieve the same result,

anEmployee = (Person *)getEmployee();                    

but the const_cast is superior for a couple of reasons. First, it's obvious and hideous. It sticks out of the code like a sore thumb, and that's a good thing, because casts in any form are dangerous. They should be painful to write, because you should use them only if you have to use them. They should be easy to find, because casts are the "usual suspects" one examines first whenever a bug appears. Second, a const_cast is less powerful than an old-style cast because it will affect only type qualifiers. This restriction is a good thing as well, because it allows us to say more precisely what our intent is. Using an old-style cast tells the compiler to shut up because you intend that the return type of getEmployee be converted to Person *. Use of a const_cast tells the compiler to shut up because you intend to strip a const from the return type of getEmployee. There is not a big difference in these two statements (although they're both pretty disrespectful, really) unless some maintenance occurs to the getEmployee function:

const Employee *getEmployee(); // big change!

The gag rule enforced by the old-style cast is still in effect; the improper conversion of const Employee * to Person * will not be flagged by the compiler, but the compiler will complain about the const_cast, because that drastic a conversion is beyond its capabilities. In short, the const_cast is preferred to the old-style cast because it's more hideous, harder to use, and less powerful.
The static_cast operator is used for casts that are relatively portable across platforms. Most commonly, it is used to cast "down" an inheritance hierarchy from a base class pointer or reference toward a derived class pointer or reference.

Shape *sp = new Circle;
Circle *cp = static_cast<Circle *>(sp); // downcast

In this case, the static_cast will result in correct code, because sp actually does refer to a Circle object. However, if sp had pointed instead to some other type of Shape, we would have likely gotten a runtime error of some sort when we used cp. To reiterate, these new cast operators are safer than old-style casts, but they're not necessarily safe.
Note that a static_cast may not change type qualifiers the way a const_cast can. This implies that it is sometimes necessary to use a sequence of two new cast operators to achieve what a single old-style cast could do:

const Shape *getNextShape() { ... }
Circle *cp =
    static_cast<Circle *>(const_cast<Shape *>(getNextShape()));

The standard doesn't guarantee much about the behavior of reinterpret_cast, but it generally does just what its name says; it looks at the bits of an object and lets you pretend they represent something else entirely:

hopeItWorks = // pretend int is pointer
    reinterpret_cast<char *>(0x00ff0000);
int *hopeless = // pretend char * is int *
    reinterpret_cast<int *>(hopeItWorks);

This sort of thing is occasionally necessary in low-level code, but it's not likely to be portable. Proceed with caution. Note the difference between reinterpret_cast and static_cast when down casting from a pointer to a base class to a pointer to a derived class. A reinterpret_cast will typically just pretend the base class pointer is a derived class pointer without changing its value whereas a static_cast will perform the correct address manipulation.
Speaking of casting within a hierarchy brings us to dynamic_cast. A dynamic_cast is used typically to perform a safe down cast from a pointer to a base to a derived. The difference from static_cast is that a dynamic_cast used as a down cast may be performed only on a polymorphic type (that is, the type of the expression being cast has to be a pointer to class type with a virtual function), and the cast actually performs a runtime check to see that the cast is correct. This safety comes at a cost, though; a static_cast typically has no or minimal runtime cost whereas using a dynamic_cast implies significant runtime overhead.

const Circle *cp =
     dynamic_cast<const Circle *>( getNextShape() );
if( cp ) { ... }

If getNextShape returns a pointer to a Circle. The cast will succeed and cp will point to a Circle. Otherwise cp will be null. Note that we can combine the declaration and test in the same expression:

if( const Circle *cp
    = dynamic_cast<const Circle *>(getNextShape()) ) { ... }

This is advantageous because it restricts the scope of the variable cp to the if-statement, so cp will just go out of scope when we no longer need it.
A less common use of dynamic_cast is to perform a down cast to a reference type:

const Circle &rc = dynamic_cast<const Circle &>(*getNextShape());

The operation is similar to that of a dynamic_cast to a pointer type, but if the cast fails, the operator throws a std::bad_cast exception rather than simply returning a null pointer. Idiomatically, a dynamic_cast to a pointer is asking a question ("Is this Shape pointer actually pointing to a Circle? If not, I can deal with it."), whereas a dynamic_cast to a reference is stating an invariant ("This Shape is supposed to be a Circle. If it's not, something is seriously wrong!").
As with the other new cast operators, use of dynamic_cast is occasionally necessary, but it is often overused because of its reputation for being a "safe" cast.

Const Pointers and Pointers to Const

In casual conversation, C++ programmers will often say "const pointer" when they really mean "pointer to const." That's unfortunate, because these are two different concepts.

T *pt = new T; // ptr to T
const T *pct = pt; // ptr to const T
T *const cpt = pt; // const ptr to T

Before you start tossing const qualifiers into your pointer declarations, you first have to decide what it is that you want to be const: the pointer, the object to which you're pointing, or both. In the declaration of pct, the pointer is not const, but the object it points to is considered to be const; that is, the const qualifier modifies the T base type, not the * pointer modifier. In the case of cpt, we're declaring a constant pointer to a non-constant object; the const qualifier modifies the * pointer modifier, not the T base type.
To further confuse the syntactic issues surrounding pointers and const, the order of the declaration specifiers (that is, everything in the pointer declaration that occurs before the first * modifier) is immaterial. For instance, the following two declarations declare variables of exactly the same type:

const T *p1; // ptr to const T
T const *p2; // also ptr to const T

The first form is more traditional, but many C++ experts now recommend the second form. The reasoning is that the second form is less prone to misunderstanding because the declaration can be read backward, as in "pointer to constant T." It doesn't really matter which form we use as long as we're consistent. Be careful, however, of the common error of confusing a declaration of a const pointer with that of a pointer to const.

T const *p3; // ptr to const
T *const p4 = pt; // const ptr to non-const

It's possible, of course, to declare a const pointer to a const.

const T *const cpct1 = pt; // everything is const
T const *const cpct2 = cpct1; // same type

Note that it's often simpler to use a reference in preference to a const pointer:

const T &rct = *pt; // rather than const T *const
T &rt = *pt; // rather than T *const

For example, we were able to initialize pct (of type const T *) with the value of pt (of type T *). The reason this is legal is that, speaking nontechnically, nothing bad can happen. Consider what happens when the address of a non-const object is copied to a pointer to const, as shown in Figure 1.

The pointer to const pct is pointing to a non-const T, but that won't cause any harm. In fact, it's common to refer to non-constant objects with pointers (or references) to const:

void aFunc( const T *arg1, const T &arg2 );
T *a = new T;
T b;
aFunc( a, b );

When we call aFunc, we initialize arg1 with a and arg2 with b. We are not claiming thereby that a points to a const object or that b is a const; we are claiming that they will be treated as if they were const within aFunc, whether or not they actually are. Very useful.
The reverse conversion, from pointer to const to pointer to non-const, is not legal because it would be dangerous, as illustrated in Figure 2.

Figure 2. A pointer to non-const may not refer to a const object.

In this case, pct may actually be pointing to an object that was defined to be const. If we could convert a pointer to const to a pointer to non-const, then pt could be used to change the value of acT.

const T acT;
pct = &acT;
pt = pct; // error, fortunately 
*pt = aT; // attempt to change const object!

The C++ standard tells us that such an assignment will have undefined results; we don't know precisely what will happen, but whatever it is won't be good. Of course, we can use a cast to perform the conversion explicitly.

pt = const_cast<T *>(pct); // not an error, but inadvisable
*pt = aT; // attempt to change const object!

However, the behavior of the assignment is still undefined if pt refers to an object that, like acT, was declared to be const.

Dealing with Function and Array Declarators

The main confusion with pointer to function and pointer to array declarations arises because the function and array modifiers have higher precedence than the pointer modifier, so parentheses are often required.

int *f1(); // function that returns int *
int (*fp1)(); // ptr to function that returns int

The same problem obtains with the high-precedence array modifier:

const int N = 12;
int *a1[N]; // array of N int *
int (*ap1)[N]; // ptr to array of N ints

Of course, once one can have a pointer to a function or to an array, one can have a pointer to such a pointer:

int (**ap2)[N]; // ptr to ptr to array of N ints
int *(*ap3)[N]; // ptr to array of N int *|
int (**const fp2)() = 0; // const ptr to ptr to func
int *(*fp3)(); // ptr to func that returns int *

Note that both the argument and return types contribute to the type of a function or function pointer.

char *(*fp4)(int,int);
char *(*fp5)(short,short) = 0;
fp4 = fp5; // error! type mismatch                                   

Things can become immeasurably more complex when function and array modifiers appear in the same declaration. Consider the following common, incorrect attempt to declare an array of function pointers:

int (*)()afp1[N]; // syntax error!                                    

In the (erroneous) declaration above, the appearance of the function modifier () signaled the end of the declaration, and the appended name afp1 signaled the start of a syntax error. It's analogous to writing an array declaration

int[N] a2; // syntax error!                                           

that works just fine in Java but is not legal C++. The correct declaration of an array of function pointers puts the name being declared in the same location that it appears in a simple pointer to function. Then we say we want an array of those things:

int (*afp2[N])(); // array of N ptr to func that returns int

Things are starting to get unwieldy here, so it's time to reach for typedef.

typedef int (*FP)(); // ptr to func that returns int
FP afp3[N]; // array of N FP, same type as afp2

The use of typedef to simplify the syntax of complex declarations is a sign of caring for those poor maintainers who come after you. Using typedef, even the declaration of the standard set_new_handler function becomes simple:

typedef void (*new_handler)();
new_handler set_new_handler( new_handler );

So, a new_handler is a pointer to a function that takes no argument and returns void, and set_new_handler is a function that takes a new_handler as an argument and returns a new_handler as a result. Simple. If you try it without typedef, your popularity with those who maintain your code will plummet:

void (*set_new_handler(void (*)()))(); // correct, but evil           

It's also possible to declare a reference to a function.

int aFunc( double ); // func
int (&rFunc)(double) = aFunc; // ref to func

References to functions are rarely used and fill pretty much the same niche as constant pointers to functions:

int (*const pFunc)(double) = aFunc; // const ptr to func

References to arrays do provide some additional capability not provided by pointers to arrays.
For more tips you can reach the author from the following Email.