C++ Class Member Initialization order....

Sample Code....
class Test
{
int x;
int y;
public:Test(int z)
{
x=y=z;
}
};
class Test1
{
Test t;
const int b;
Test1(int z):t(1),b(10)
{

}
};



CSomeClass::CSomeClass()
{
x=0;
y=1;
}

and in other places I see it written this way:



CSomeClass::CSomeClass() : x(0), y(1)
{
}

Some of my programmer friends say that it's better to do it the second way, but no one knows why. Can you tell me the difference between these two methods of initializing class members?
A
Technically your friends are right, but in most cases it makes no difference. There are two reasons to use the second syntax, which is called a member initialization list: one is necessity, the other efficiency.
Let's examine the first reasonâ€"necessity. Suppose you have a class member that is itself a class or struct, and this class only has one constructor that requires an argument.



class CMember {
public:
CMember(int x) { ... }
};

Since CMember has an explicit constructor, the compiler does not generate a default constructor (one with no arguments) and there is no way to create an instance of CMember without an integer.



CMember* pm = new CMember; // Error!!
CMember* pm = new CMember(2); // OK

How do you initialize CMember if it's a member of another class? You must use the member initialization list.



class CMyClass {
CMember m_member;
public:
CMyClass();
};
// must use initializer list
CMyClass::CMyClass() : m_member(2)

{
•••
}

There's simply no other way to pass the argument to m_member. The same is true if the member is a const object or reference. According to the rules of C++, const objects and references cannot be assigned; they can only be initialized.
The second reason for using the initializer listâ€"efficiencyâ€"arises when the member class has a default constructor as well as an assignment operator. MFC's CString offers a perfect example. Say you have a class CMyClass with a CString member m_str and you want to initialize m_str to "yada yada." You have two choices



CMyClass::CMyClass() {
// use assignment operator
// CString::operator=(LPCTSTR);
m_str = _T("yada yada");
}

or



// use initializer list
// and constructor CString::CString(LPCTSTR)
CMyClass::CMyClass() : m_str(_T("yada yada"))
{
}

Is there any difference between these methods? Yes. The compiler always insures that all member objects are initialized before the body of the constructor executes, so in the first example the compiled code will call CString::CString to initialize m_str before control reaches the assignment statement. In the second example, the compiler generates a call to CString:: CString(LPCTSTR), passing "yada yada" as the string. The upshot is that in the first example two CString functions are called (constructor and assignment operator), whereas in the second example only one function is called.
In the case of CString it hardly matters, since the default constructor is inline and CString only allocates storage for the string when it's needed (that is, when you actually set it to something). But, in general, the duplicate function call can be wasteful, particularly if both constructor and assignment operator allocate storage. In some large classes, you may have a constructor and assignment operator that both call the same Init function, which allocates a large amount of memory. In that particular case, you must use the initializer list in order to avoid needlessly allocating the storage twice.
In the case of built-in types like ints or longs or other types with no constructors, there's no performance difference between initializing an int in the initializer list or assigning it in the constructor body. Either way, there will be one assignment. Some programmers say you should always use the initializer list just to get in the habit, but I have never found it difficult to switch between the two methods as needed. Stylistically, I prefer assignment in the body because there's more room for formatting and comments, and you can write things like



x=y=z=0;

or



memset(this,0,sizeof(this));

Note that the second snippet is decidedly non-object-oriented.
While I'm on the subject of initializer lists, there's one peculiar feature I should warn you about. C++ initializes class members in the order they are declared, not the order they appear in the initializer list.



class CMyClass {
CMyClass(int x, int y);
int m_x;
int m_y;
};
CMyClass::CMyClass(int i) : m_y(i), m_x(m_y)
{
}

You might think that the previous code would first assign m_y=i and then m_x=m_y so that both m_x and m_y would have the same value. But the compiler initializes m_x first then m_y, since that's the order in which they are declared. The result is that m_x will have an unpredictable value. My example is contrived to illustrate the point, but there are times when this bug arises more naturally. There are two ways to avoid it. First, always declare members in the order you want them initialized. Second, if you decide to use an initializer list, always list the members in the same order they're declared. This will help you avoid confusion.

Good Artical:::
MSDN artical

Comments

Popular posts from this blog

XML Programming using IXMLDOMDOCUMENT in vc++

Get correct OS version on win 8.1 without using GetVesionEx API (deprecated )