You can use the technique known as a member initialization list to initialize members of a class.

"Allocating memory" and "assigning memory location" has nothing to do with anything here. You are asking about how objects that are members of another class get constructed. Trying to pull in the subject of memory allocation here only confuses things. Advanced C++ techniques allow objects to be repeatedly constructed and destroyed "in the same place" (via placement new and explicit destructor invocations). Actual memory locations, and object constructions/destructions, are completely immaterial. They have nothing to do with each other, and it will be helpful if you simply forget everything about memory locations, and focus only on the topic of object construction and destruction. Having said all of that:

An object constructor is responsible for constructing all members of the object. That's the rule. No exceptions. Full stop.

student(): u(university("ABC")){

This will work, but this also does this in a confusing member. This spells out the following sequence of events: a temporary university object gets constructed, then copy-constructs the actual member of the student class, finally the temporary object gets destroyed. This is unnecessary and only serves to muddy the waters. Using a simpler, modern C++ syntax, this should be:

student(): u{"ABC"}{

This shorter, direct syntax, describes exactly what's going on in a simple, concise manner: the object's constructor constructs all members of this object, namely just one, here. It's called u. u's constructor gets invoked passing to it a character string as a parameter. The university's "parametrized" constructor gets called. A constructor's member initialization section is nothing more than a simple list: here are my class members, and here are the parameters to their respective constructors. Abracadabra: they're constructed.

student() {

If a constructor does not have a member initialization section, or does not list the object's member in the initialization section, the corresponding class members' default constructors get called.

That's it, that's all there is to it: your class *here the class is called student) has members, and the class's constructor explicitly initializes them, the corresponding constructor gets called, for the class members. If any class member is not listed in the initialization section its default constructor gets called, if the class member does not have a default constructor the resulting code is ill-formed and won't compile.

Skip to main content

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.

  • Article
  • 10/25/2019
  • 10 minutes to read

In this article

You can use the technique known as a member initialization list to initialize members of a class.

You can use the technique known as a member initialization list to initialize members of a class.

Initializing C++ Class Members and Incorporating the Places Bar in your MFC Apps

Paul DiLascia

Q I have a question about initializing class members in C++. I see a lot of code (your column included) that does this:

  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.

Q I've just installed Windows® 2000 Release Candidate 1 on a few machines and am wondering how to get the new Open dialog with the Outlook-style bar on the left side (see Figure 1) in my MFC applications.

You can use the technique known as a member initialization list to initialize members of a class.

Figure 1 The New Open Dialog

Can I just set a flag, or do I need new header files and a new common dialog DLL? I've noticed that some older apps like Notepad seem to get the new Open dialog without recompiling, but not MFC apps. Ideally, I want an app that uses the old dialog on Windows 9x and Windows NT®, and the new dialog on Windows 2000.

Warren Stevens

A I'm afraid there's no happy answer to this one. The new Open dialog in Windows 2000, which contains the "Places" bar on the side, is implemented in a new version of commdlg.dll. The function that displays it is GetOpenFileName, the same function that was used in Windows 9x and Windows NT. However, GetOpenFileName now uses a new version of OPENFILENAME, the struct that passes information between your app and the dialog. The new struct has some additional members:

  typedef struct tagOFN {
DWORD lStructSize; // important!
•••
// as you've always known and loved it
#if (_WIN32_WINNT >= 0x0500)
void* pvReserved;
DWORD dwReserved;
DWORD FlagsEx;
#endif // (_WIN32_WINNT >= 0x0500)
} OPENFILENAME, *LPOPENFILENAME;

      Yes, that's right. Windows 2000 bumps the Windows version number to 5, which in hexalese is 0x500. If you compile your program with _WIN32_WINNT = 0x0500, then OPENFILENAME gets the three new members. The first two are reserved. The third flags field, FlagsEx, has a new OFN_EX_NOPLACESBAR flag that suppresses the Places bar. Windowsâ€"or more precisely, commdlg.dllâ€"uses the first member of OPENFILENAME, lStructSize, to determine which dialog to display. If lStructSize is 76 (the old size), Windows runs the old dialog; if it's 76+3�4=88 (the new size), it runs the new dialogâ€"or so the friendly Redmondtonians originally informed me. During my explorations, I discovered that this isn't the whole picture.
      But before I get into that, let's pop over to MFC land to look at another problem. In an MFC app, you don't usually call GetOpenFileName directly. Instead, you use CFileDialogâ€"or rather, the framework does. When the user invokes File | Open, control tumbles through CWinApp::OnFileOpen and several functions to eventually arrive at CDocManager::DoPromptFileName (of all places), which creates a CFileDialog. CFileDialog has the OPENFILENAME struct within it as a data member:

  class CFileDialog : public CCommonDialog {
OPENFILENAME m_ofn;
•••
};

      The size of this structure is whatever the size of OPENFILENAME was when the friendly Redmondtonians compiled MFC42.DLL; in other words, the old size. Moreover, the MFC code is frozen for all time in MFC42.DLL, or NAFXCW.LIB if you're doing a static link. You can't just set m_ofn.lStructSize to the new size since CFileDialog has some other data members following m_ofn, which would then get overwritten by the new OPENFILENAME members.
      Not to be deterred, I set out to circumvent the problem using extreme methods. I figured I could do something similar to what MFC does with CPropertyPage. The sizes of PROPSHEETPAGE and PROPSHEETHEADER grew somewhere along the way from Windows 95 to Windows 98 in order to support wizard-style pages. To support the newly inflated structs, MFC came out with CPropertyPageEx and CPropertySheetEx. The original classes (without the Ex) still use the old structs; the new classes use the new ones. It's a kind of kludge, especially since afxdlgs.h has its own definition of the old structs (AFX_ OLDPROPSHEETPAGE and AFX_OLDPROPSHEETHEADER), but it works.
      I did the same thing with CFileDialog. I derived a new CFileDialogEx with a new m_ofn that has a new OPENFILENAMEEX struct, which I defined to mimic the 0x500 version. I added the three new members and reimplemented all the CFileDialog functions that use m_ofn. Unfortunately, since most of the MFC code is hardwired with no virtual functions, this meant copying practically the whole class. But I was determined.
      After I thought I'd found every place m_ofn is used, I rewrote it, happily compiled my code (on Windows 98), and ran itâ€"only to discover that I was still getting the old-style dialog. Moreover, there was another mystery I'd forgotten to consider: if Windows 2000 uses lStructSize to decide which Open dialog to run, why do some Windows 98-based apps (like Notepad) get the new dialog when you run them as is on Windows 2000? Whoa! The NOTEPAD.EXE that comes with Windows 98 obviously has the old OPENFILENAME size in lStructSize, so Windows 2000 must be using something more than lStructSize to determine which dialog to run.
      At this point I decided to step back. I set MFC aside and tried calling GetOpenFileName directly. I rewrote my app's OnFileOpen:

  void CMyApp::OnFileOpen()
{
OPENFILENAME ofn; // older version
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
int nResult = ::GetOpenFileName(&ofn);
}

Since all through this exercise I was using the older version 0x400 SDK files (because I wanted to build an app that runs on Windows 9x as well as Windows 2000), ofn.lStructSize gets the old size. When I compiled and ran this code, I got the old dialog on Windows 98 and the new dialog on Windows 2000â€"just like Notepad! So Windows 2000 is, in fact, smart enough to use the new dialog for old appsâ€"but not old MFC apps. It makes no sense. What's different about an MFC app?
      It must be the flags. To find out, I manually added various flags to my OPENFILENAME struct one at a time until my program produced the old-style dialog without the Places bar. Lo and behold, it turned out that as soon as I added the flag OFN_ENABLEHOOK to ofn.Flags, my dialog reverted to its historical self. I then reported this odd behavior to the Redmondtonians, who confirmed "this behavior is by design."
      So Windows 2000 keys on the size of the OPENFILENAME struct and whether the dialog uses a hook procedure. If OPENFILENAME has the old size, Windows 2000 uses OFN_ENABLEHOOK to determine which dialog to use. If the OPENFILENAME uses a hook procedure (or ORN_ENABLETEMPLATE is set), Windows 2000 displays the old-style dialog; otherwise, it displays the new one. This explains why MFC apps get the old dialogâ€"because CFileDialog, like all MFC common dialogs, uses a hook procedure. That's how MFC wires a common dialog into its message map system, the same way it uses AfxWndProc to wire ordinary windows.
      So the upshot is: you're hosed. The only way to get the new-style dialog in an MFC app is to shuck CFileDialog completely and call GetOpenFileName directly, without using a hook procedure. Even if you compile your app with the new SDK files and WINVER = 0x500, you still can't use MFC because its libraries and DLLs have the old size compiled in. You could recompile MFC yourself, using WINVER = 0x500, but who knows what that would do. And if you do build a new MFC, you'll have to distribute the new DLL with your application and name it something else, since your new MFC DLL will certainly be incompatible with other MFC apps that expect CFileDialog and other structures to have the old size. Alternatively, you could rebuild MFC and link it statically, which will increase your executable size dramatically. Failing that you could reimplement Windows.
 As of press time, I have word from Redmond that there will be a new (renamed) version of the MFC DLL in upcoming releases of Visual C++®. The new version of MFC will support the new UI and APIs exposed in Windows 2000. Meanwhile, I leave you to ponder Figure 2, taken from the latest SDK documentation, "Header File Conventions," which provides the key to Windows versionitis. It indicates which macros you must define to target specific versions of Windows and Microsoft® Internet Explorer using SDK headers. Try not to let life in the fast lane get you down.

Paul DiLascia is the author of Windows++: Writing Reusable Windows Code in C++ (Addison-Wesley, 1992) and a freelance consultant and writer-at-large. He can be reached at or https://www.dilascia.com.

From the April 2000 issue of MSDN Magazine.

How do you initialize a class member in C++?

There are two ways to initialize a class object: Using a parenthesized expression list. The compiler calls the constructor of the class using this list as the constructor's argument list. Using a single initialization value and the = operator.

Which type of member function may only be called from a function that is a member of the same class?

A private member function may only be called from a function that is a member of the same class.

Which of the following is used to initialize data members?

Constructor is used to initialize the data members of a | KnowledgeBoat.

Which operator can be used by an object to access members of the class?

Accessing the members of the class (data and functions) is done using the dot (.) operator, which is also called as the member access operator. If obj is the name of the object and there is a function “display ()” in the class, then the function can be accessed as “obj. display ()”.