cppreference.com

Constructors and member initializer lists.

Constructors are non-static member functions declared with a special declarator syntax, they are used to initialize objects of their class types.

In the definition of a constructor of a class, member initializer list specifies the initializers for direct and virtual bases and non-static data members. (Not to be confused with std::initializer_list .)

[ edit ] Syntax

Constructors are declared using member function declarators of the following form:

Where class-name must name the current class (or current instantiation of a class template), or, when declared at namespace scope or in a friend declaration, it must be a qualified class name.

The only specifiers allowed in the decl-specifier-seq of a constructor declaration are friend , inline , constexpr (since C++11) , consteval (since C++20) , and explicit (in particular, no return type is allowed). Note that cv- and ref-qualifiers are not allowed either: const and volatile semantics of an object under construction don't kick in until the most-derived constructor completes.

The body of a function definition of any constructor, before the opening brace of the compound statement, may include the member initializer list , whose syntax is the colon character : , followed by the comma-separated list of one or more member-initializers , each of which has the following syntax:

[ edit ] Explanation

Constructors have no names and cannot be called directly. They are invoked when initialization takes place, and they are selected according to the rules of initialization. The constructors without explicit specifier are converting constructors . The constructors with a constexpr specifier make their type a LiteralType . Constructors that may be called without any argument are default constructors . Constructors that take another object of the same type as the argument are copy constructors and move constructors .

Before the compound statement that forms the function body of the constructor begins executing, initialization of all direct bases, virtual bases, and non-static data members is finished. The member initializer list is the place where non-default initialization of these subobjects can be specified. For bases that cannot be default-initialized and for non-static data members that cannot be initialized by default-initialization or by their default member initializer , if any (since C++11) , such as members of reference and const-qualified types, member initializers must be specified. (Note that default member initializers for non-static data members of class template instantiations may be invalid if the member type or initializer is dependent.) (since C++11) No initialization is performed for anonymous unions or variant members that do not have a member initializer or default member initializer (since C++11) .

The initializers where class-or-identifier names a virtual base class are ignored during construction of any class that is not the most derived class of the object that's being constructed.

Names that appear in expression-list or brace-init-list are evaluated in scope of the constructor:

Exceptions that are thrown from member initializers may be handled by function-try-block

Member functions (including virtual member functions) can be called from member initializers, but the behavior is undefined if not all direct bases are initialized at that point.

For virtual calls (if the direct bases are initialized at that point), the same rules apply as the rules for the virtual calls from constructors and destructors: virtual member functions behave as if the dynamic type of * this is the static type of the class that's being constructed (dynamic dispatch does not propagate down the inheritance hierarchy) and virtual calls (but not static calls) to pure virtual member functions are undefined behavior.

Reference members cannot be bound to temporaries in a member initializer list:

Note: same applies to default member initializer .

[ edit ] Initialization order

The order of member initializers in the list is irrelevant: the actual order of initialization is as follows:

(Note: if initialization order was controlled by the appearance in the member initializer lists of different constructors, then the destructor wouldn't be able to ensure that the order of destruction is the reverse of the order of construction.)

[ edit ] Notes

[ edit ] example, [ edit ] defect reports.

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

[ edit ] References

  • C++23 standard (ISO/IEC 14882:2023):
  • 11.4.5 Constructors [class.ctor]
  • 11.9.3 Initializing bases and members [class.base.init]
  • C++20 standard (ISO/IEC 14882:2020):
  • 11.4.4 Constructors [class.ctor]
  • 11.10.2 Initializing bases and members [class.base.init]
  • C++17 standard (ISO/IEC 14882:2017):
  • 15.1 Constructors [class.ctor]
  • 15.6.2 Initializing bases and members [class.base.init]
  • C++14 standard (ISO/IEC 14882:2014):
  • 12.1 Constructors [class.ctor]
  • 12.6.2 Initializing bases and members [class.base.init]
  • C++11 standard (ISO/IEC 14882:2011):
  • C++98 standard (ISO/IEC 14882:1998):

[ edit ] See also

  • copy elision
  • converting constructor
  • copy assignment
  • copy constructor
  • default constructor
  • aggregate initialization
  • constant initialization
  • copy initialization
  • default initialization
  • direct initialization
  • list initialization
  • reference initialization
  • value initialization
  • zero initialization
  • move assignment
  • move constructor
  • Recent changes
  • Offline version
  • What links here
  • Related changes
  • Upload file
  • Special pages
  • Printable version
  • Permanent link
  • Page information
  • In other languages
  • This page was last modified on 12 February 2024, at 05:55.
  • This page has been accessed 2,786,726 times.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

9.6. Constructors And Initializer Lists

Please review the following concepts as needed:

  • Function basics
  • Function definitions
  • Function prototypes
  • Pass by value
  • Pass by reference
  • Return by value
  • Default arguments
  • Overloaded functions
  • const Reference Arguments

Constructors are, first and foremost, just functions. They can range from simple to complex. However, constructors are special functions that are called automatically whenever a program creates (i.e., instantiates) a new object. The primary purpose of constructors is to construct or initialize an object. Visually, constructors are set apart from "regular" functions by two characteristics: (a) they have the same name as the class for which they are constructing objects, and (b) they do not have a return type.

Constructors

As you might suppose, constructors are an essential part of object-oriented programs, enough so that we name five different kinds to make them easier to talk about.

  • Calls the default, no-argument constructor. Historically, a call to the default constructor did not allow parentheses, but a recent change to the ANSI C++ standard now permits them
  • Calls the one-argument constructor
  • Calls the two-argument constructor

Each constructor is designed to fill a specific programming need, but most classes will only need a few constructors - not all. The following sections describe each kind of constructor in detail, but the focus is on the constructor's visible operations. One object-oriented feature, polymorphism, requires that each object store a hidden pointer (called the vptr or virtual pointer). One of the tasks of every constructor is to initialize vptr , which it does by running code that the compiler automatically inserts into each constructor. If the class does not have any constructors, the compiler creates a simple default constructor to initialize the vptr . We'll explore polymorphism in more detail in a later chapter.

As described below, we typically distinguish constructors based on their parameters. However, we use the term "general constructor" to denote any constructor that doesn't fit into one of the other categories. Further confusing constructor identification, sometimes we need a general constructor having only one parameter, but we don't use it as a conversion constructor. Sometimes the distinction between a general and conversion constructor is how we use it rather than the number of parameters. We'll see in the CString example later in the chapter that this can sometimes cause problems.

The Default Constructor

The primary characteristic that sets a default constructor apart from the other constructors is that it has no parameters. A default constructor often creates an "empty" object or an initialized object with default values. Although the text didn't state it at the time, many of our previous examples have relied on the string class default constructor that creates a string object that does not contain any characters. We can also use a default constructor to create an "empty" instance of our Time class.

  • For much of C++'s life, initializing data members in the class specification was not allowed. So, providing a default constructor was the only option for programmers to provide default values to new objects.
  • The ANSI 2014 standard added member initialization in the class specification (highlighted). In-class initialization is a compact, easily used notation for initializing data members when the program instantiates a new object.
  • If programmers add a parameterized constructor (highlighted) to a class, they are saying, in a sense, "This is the only way you can create an instance of my class." The existence of a parameterized constructor precludes instantiating an object without providing the parameter values, rendering the in-class initializations superfluous.
  • Adding a "dummy" or do-nothing default constructor (highlighted) allows programmers to instantiate an object without providing parameter values. In this case, the in-class initialization supplies the data member's initial values.
  • Older versions of C++ neither required nor allowed parentheses when calling a default constructor.
  • Newer standards make the parentheses optional.

Conversion Constructor

A conversion constructor converts one data type into an instance of the class in which the constructor appears. What the conversion means and how the conversion function works depends solely on the source and destination types. A conversion constructor has one argument, and the one highlighted in the following example converts an int into an instance of the Time class:

The conversion constructor illustrated above is the second make_time function from the struct Time example rewritten as a constructor. It is possible to generalize the pattern of a conversion constructor as follows:

Where Bar may be the name of a primitive, built-in data type, or it may be the name of a class. Here is another example of a conversion constructor based on strings and C-strings:

The definition of variable s converts a C-string ("Hello, World!") into the string object s .

Copy Constructor

A copy constructor creates a new object by copying an existing object. C++ bases two critical and fundamental programming operations on the copy constructor:

This means that whenever functions pass or return objects by value, the program copies the objects from one part of the program to another. Each operation creates a new object, and constructing new objects is always the task of a constructor function. These operations are so fundamental to programming that the compiler automatically generates a copy constructor for every class. In the previous examples, copying an existing object is easy enough for the compiler to create the constructor automatically. Later, we will see more complex situations where the compiler-generated copy constructor is insufficient, and in such cases, we must override it with our own constructor.

Since the copy constructor implements pass-by-value (i.e., passing an object by value), its argument cannot be passed by value (which would cause infinite recursion). For this reason, copy constructors have a particular signature that makes them easy to identify and which programmers must follow when overriding the compiler-generated copy constructor. Copy constructors always require a single argument that is the same class type as the class in which the constructor appears, and the parameter is always a reference variable:

If one or more member variables is a pointer, the copy operation becomes more complex, and we defer dealing with this situation until the next chapter. For the curious or those facing a more immediate problem, please see The Copy Constructor in the next chapter.

  • This version of the add function causes three implicit or "hidden" function calls. The first implicit call is to the default constructor (highlighted in yellow). The return statement (highlighted in orange) calls the copy constructor to return the object and a destructor to destroy temp .
  • The second version requires a general or parameterized constructor but saves two function calls. The object created in the return statement is constructed in the calling scope rather than the function's scope. So, this version does not make a destructor call and only makes one general constructor call (yellow).

Move Constructor

Like the copy constructor, the move constructor can be identified by its distinctive argument list:

If a move constructor has additional arguments, they must have default values (i.e., default arguments ). Unlike copy constructors, move constructors can take some or all the resources held by the argument object rather than copying them. The argument object remains in a valid but potentially incomplete state. Our move constructor study doesn't extend beyond recognizing and identifying it. The double ampersand, && , which denotes an r-value reference declarator, and the move constructor are otherwise beyond the scope of CS 1410, but you'll study them in detail in CS 2420.

General Constructor

No special syntax or pattern defines a general constructor. A general constructor simply does not fit into one of the previously described categories above. So, any constructor that has two or more parameters is a general constructor just because it's not (a) a default constructor (no parameters), (b) a conversion constructor (has one parameter that's not a reference), or (c) a copy constructor (one parameter that is a reference). It is possible to convert the first make_time function from the struct Time example into a general constructor:

Initializer List Notation

One common task of constructor functions is initializing (i.e., assigning the first or initial value to) an object's member variables, regardless of the constructor's overall complexity. Although programmers can initialize members in the constructor's body, most practitioners consider it a better practice to initialize them with an initializer list. An initializer list is a compact notation equivalent to a sequence of assignment statements. But they have the advantage of running before the constructor's body, so the member variables are ready to use as soon as the body runs. Initializer lists begin with a colon and appear between a function's parameter list and the body's opening brace. Initializer lists follow a simple pattern :

An initializer list is a comma-separated list of initializer elements. Each element behaves like an assignment, so numerator(n) is equivalent to numerator = n . The color coding in the figure above highlights the connection between a constructor's arguments and member variables: the first part of each element is the name of a member variable, and the second part (enclosed in parentheses) is the name of one of the function's parameters. With one exception, the list elements may appear in any order. We'll explore that exception, inheritance, in the next chapter.

  • The constructor body has one assignment operation for each member variable and each constructor argument. I've deliberately written the function to emphasize the difference between the two illustrated techniques, but in fairness, we can simplify this version: int common = gcd(n, d); numerator = n / common; denominator = d / common;
  • An initializer list (highlighted) behaves like a series of assignment operations but is preferred to the explicit assignment because it takes place before any statements in the constructor body run

An illustration of data flowing from a constructor function call into an object's member variables. Data enters a constructor through an argument. The initializer list uses the argument's name to store the data in a member variable.

  • The variable p is an instance of class Person ; when a program instantiates a class, it automatically calls a constructor function and passes the arguments, Dilbert , 5.9 , and 150 , to the constructor's parameters
  • The data from the constructor call is passed into the function's parameters, which are variables named a_name , a_height , and a_weight
  • The variable names in the function parameter list are used in the initializer list that appears on the right side of the colon
  • Each element of the initializer list consists of a member variable name followed, in parentheses, by the name of a constructor parameter

Every function must have exactly one body. The body is often empty in the case of simple constructors whose only purpose is to initialize the object's member variables. In the following example, the {} at the end is the function's empty body and not part of the initializer list.

Initializer lists are a part of the function definition and not of the declaration or prototype. So, if the class only contains a function prototype and the function definition is in a separate .cpp file, then the initializer list goes with the function definition in the .cpp file:

Default Arguments

Although the UML has always permitted class designers to specify initial values for member variables and function arguments, C++ originally did not allow programmers to initialize member variables in the class specification. So, programmers initialized member variables with constructors, and you may still see examples of this in existing code. However, C++ has always supported default arguments , which may be used with any C++ function (not just constructors). When we use default arguments with constructors, they must follow all of the rules listed in chapter 6 (and it's probably a good idea to review those rules now).

  • The UML constructor
  • is translated into the C++ code

In "real world" C++ programs, it is common for the class specification to appear in a .h file and the member functions (including constructors) to appear in a .cpp file. When we follow this organization, there is one unfortunate aspect of initializer lists and constructor default arguments that we must memorize:

  • fraction(); // acts as a default constructor
  • fraction(n); // acts as a conversion constructor
  • fraction(n,d);
  • Initializer lists appear with the function DEFINITION in the source code (i.e., .cpp ) file.

If a class only needs a constructor to initialize the member variables, replacing the constructor with initializations directly in the class specification is appropriate. The compiler will automatically create a default constructor to initialize the vptr as needed. However, initializing member variables directly inside the class specification doesn't always replace a default constructor or default arguments when object construction requires operations more complex than member initialization. Furthermore, if the class defines one or more parameterized constructors, then a default constructor or default arguments are still needed if the programmer wishes to create an object without calling a parameterized constructor:

Constructor Chaining

Like any function, constructors can range from algorithmically simple to complex. Sometimes complex constructors perform the same operations as simple ones, followed by additional operations befitting their complex nature. We can often avoid the overhead of writing and maintaining duplicate constructor code by putting the common, often simple, code in a basic constructor and allowing more advanced constructors to call the basic one. Java has always supported in-class constructor chaining by using this(...) as the name of an overloaded constructor and the number and type of arguments to differentiate between them. Before the adoption of the C++ 2011 standard, C++ did not permit in-class constructor chaining, but it does now, albeit with limitations.

  • A class that implements a table as a two-dimensional array. rows and cols are the numbers of rows and columns in the table, respectively. array is a pointer to an array of pointers that make up the table rows.
  • A "simple" constructor that initializes the data members. The for-loop creates one table row during each iteration. Note that the initializer list initializes rows and cols before the statements in the body of the constructor run.
  • Delegation describes the situation where one member function calls another - the caller delegates some of its responsibility to the called function. This example illustrates the copy constructor implemented as a delegation constructor - it calls the constructor illustrated in (b), highlighted in yellow, to create a new Table object and then copies the contents of this object to the new object. Any constructor can delegate to another, so "delegation constructor" is not included in the named constructors above.
  • C++ imposes a severe restriction on delegation: it only allows one initializer in the initializer list. Assume for a moment that the Table class has a data member named member . Ordinarily, we could initialize member using the operation highlighted in coral. But doing this results in a list with two comma-separated initializers, and the highlighted code is an error.

Chaining constructors works well when the operations of the called or delegated constructor (e.g., (b)) must or can run before the operations in the calling or delegating constructor (e.g., (c)). When that is not the case, the best we can do, in C++ or Java, is use a helper function to implement the common code.

  • A helper function named display that displays a Window object. Programmers typically put helpers in the class's private section, so users cannot call them directly.
  • Creates a simple Window , perhaps using default values. The constructor displays the window following its initialization.
  • The user of the Window class specifies the coordinates of the upper left-hand corner of the window ( x and y ) when creating the object and then displays it.
  • In the final example, the constructor has three parameters: the location on the screen at (x,y) and the color of the window. Like the example (c), the helper function displays the window when its initialization is complete.

1 A bitwise copy simply means that the computer copies a patch of bits, bit-for-bit, from one memory location to another. A program can perform the copy operation with the memcpy function, which many computers support with a single machine instruction (and so it is very fast and efficient). For example, given the following code fragment:

The compiler can create a simple copy constructor with a single statement:

This browser is no longer supported.

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

Constructors (C++)

  • 13 contributors

To customize how a class initializes its members, or to invoke functions when an object of your class is created, define a constructor . A constructor has the same name as the class and no return value. You can define as many overloaded constructors as needed to customize initialization in various ways. Typically, constructors have public accessibility so that code outside the class definition or inheritance hierarchy can create objects of the class. But you can also declare a constructor as protected or private .

Constructors can optionally take a member initializer list. It's a more efficient way to initialize class members than assigning values in the constructor body. The following example shows a class Box with three overloaded constructors. The last two use member init lists:

When you declare an instance of a class, the compiler chooses which constructor to invoke based on the rules of overload resolution:

  • Constructors may be declared as inline , explicit , friend , or constexpr .
  • A constructor can initialize an object that has been declared as const , volatile or const volatile . The object becomes const after the constructor completes.
  • To define a constructor in an implementation file, give it a qualified name like any other member function: Box::Box(){...} .

Member initializer lists

A constructor can optionally have a member initializer list , which initializes class members before the constructor body runs. (A member initializer list isn't the same thing as an initializer list of type std::initializer_list<T> .)

Prefer member initializer lists over assigning values in the body of the constructor. A member initializer list directly initializes the members. The following example shows the member initializer list, which consists of all the identifier(argument) expressions after the colon:

The identifier must refer to a class member; it's initialized with the value of the argument. The argument can be one of the constructor parameters, a function call or a std::initializer_list<T> .

const members and members of reference type must be initialized in the member initializer list.

To ensure base classes are fully initialized before the derived constructor runs, call any parameterized base class constructors in the initializer list.

Default constructors

Default constructors typically have no parameters, but they can have parameters with default values.

Default constructors are one of the special member functions . If no constructors are declared in a class, the compiler provides an implicit inline default constructor.

If you rely on an implicit default constructor, be sure to initialize members in the class definition, as shown in the previous example. Without those initializers, the members would be uninitialized and the Volume() call would produce a garbage value. In general, it's good practice to initialize members in this way even when not relying on an implicit default constructor.

You can prevent the compiler from generating an implicit default constructor by defining it as deleted :

A compiler-generated default constructor will be defined as deleted if any class members aren't default-constructible. For example, all members of class type, and their class-type members, must have a default constructor and destructors that are accessible. All data members of reference type and all const members must have a default member initializer.

When you call a compiler-generated default constructor and try to use parentheses, a warning is issued:

This statement is an example of the "Most Vexing Parse" problem. You could interpret myclass md(); either as a function declaration or as the invocation of a default constructor. Because C++ parsers favor declarations over other things, the expression is treated as a function declaration. For more information, see Most Vexing Parse .

If any non-default constructors are declared, the compiler doesn't provide a default constructor:

If a class has no default constructor, an array of objects of that class can't be constructed by using square-bracket syntax alone. For example, given the previous code block, an array of Boxes can't be declared like this:

However, you can use a set of initializer lists to initialize an array of Box objects:

For more information, see Initializers .

Copy constructors

A copy constructor initializes an object by copying the member values from an object of the same type. If your class members are all simple types such as scalar values, the compiler-generated copy constructor is sufficient and you don't need to define your own. If your class requires more complex initialization, then you need to implement a custom copy constructor. For example, if a class member is a pointer then you need to define a copy constructor to allocate new memory and copy the values from the other's pointed-to object. The compiler-generated copy constructor simply copies the pointer, so that the new pointer still points to the other's memory location.

A copy constructor may have one of these signatures:

When you define a copy constructor, you should also define a copy assignment operator (=). For more information, see Assignment and Copy constructors and copy assignment operators .

You can prevent your object from being copied by defining the copy constructor as deleted:

Attempting to copy the object produces error C2280: attempting to reference a deleted function .

Move constructors

A move constructor is a special member function that moves ownership of an existing object's data to a new variable without copying the original data. It takes an rvalue reference as its first parameter, and any later parameters must have default values. Move constructors can significantly increase your program's efficiency when passing around large objects.

The compiler chooses a move constructor when the object is initialized by another object of the same type, if the other object is about to be destroyed and no longer needs its resources. The following example shows one case when a move constructor is selected by overload resolution. In the constructor that calls get_Box() , the returned value is an xvalue (eXpiring value). It's not assigned to any variable and is therefore about to go out of scope. To provide motivation for this example, let's give Box a large vector of strings that represent its contents. Rather than copying the vector and its strings, the move constructor "steals" it from the expiring value "box" so that the vector now belongs to the new object. The call to std::move is all that's needed because both vector and string classes implement their own move constructors.

If a class doesn't define a move constructor, the compiler generates an implicit one if there's no user-declared copy constructor, copy assignment operator, move assignment operator, or destructor. If no explicit or implicit move constructor is defined, operations that would otherwise use a move constructor use the copy constructor instead. If a class declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted.

An implicitly declared move constructor is defined as deleted if any members that are class types lack a destructor or if the compiler can't determine which constructor to use for the move operation.

For more information about how to write a non-trivial move constructor, see Move Constructors and Move Assignment Operators (C++) .

Explicitly defaulted and deleted constructors

You can explicitly default copy constructors, default constructors, move constructors, copy assignment operators, move assignment operators, and destructors. You can explicitly delete all of the special member functions.

For more information, see Explicitly Defaulted and Deleted Functions .

constexpr constructors

A constructor may be declared as constexpr if

  • it's either declared as defaulted or else it satisfies all the conditions for constexpr functions in general;
  • the class has no virtual base classes;
  • each of the parameters is a literal type ;
  • the body isn't a function try-block;
  • all non-static data members and base class subobjects are initialized;
  • if the class is (a) a union having variant members, or (b) has anonymous unions, only one of the union members is initialized;
  • every non-static data member of class type, and all base-class subobjects have a constexpr constructor

Initializer list constructors

If a constructor takes a std::initializer_list<T> as its parameter, and any other parameters have default arguments, that constructor is selected in overload resolution when the class is instantiated through direct initialization. You can use the initializer_list to initialize any member that can accept it. For example, assume the Box class (shown previously) has a std::vector<string> member m_contents . You can provide a constructor like this:

And then create Box objects like this:

Explicit constructors

If a class has a constructor with a single parameter, or if all parameters except one have a default value, the parameter type can be implicitly converted to the class type. For example, if the Box class has a constructor like this:

It's possible to initialize a Box like this:

Or pass an int to a function that takes a Box:

Such conversions can be useful in some cases, but more often they can lead to subtle but serious errors in your code. As a general rule, you should use the explicit keyword on a constructor (and user-defined operators) to prevent this kind of implicit type conversion:

When the constructor is explicit, this line causes a compiler error: ShippingOrder so(42, 10.8); . For more information, see User-Defined Type Conversions .

Order of construction

A constructor performs its work in this order:

It calls base class and member constructors in the order of declaration.

If the class is derived from virtual base classes, it initializes the object's virtual base pointers.

If the class has or inherits virtual functions, it initializes the object's virtual function pointers. Virtual function pointers point to the class's virtual function table to enable correct binding of virtual function calls to code.

It executes any code in its function body.

The following example shows the order in which base class and member constructors are called in the constructor for a derived class. First, the base constructor is called. Then, the base-class members are initialized in the order in which they appear in the class declaration. Finally, the derived constructor is called.

Here's the output:

A derived class constructor always calls a base class constructor, so that it can rely on completely constructed base classes before any extra work is done. The base class constructors are called in order of derivation—for example, if ClassA is derived from ClassB , which is derived from ClassC , the ClassC constructor is called first, then the ClassB constructor, then the ClassA constructor.

If a base class doesn't have a default constructor, you must supply the base class constructor parameters in the derived class constructor:

If a constructor throws an exception, the order of destruction is the reverse of the order of construction:

The code in the body of the constructor function is unwound.

Base class and member objects are destroyed, in the reverse order of declaration.

If the constructor is non-delegating, all fully constructed base class objects and members are destroyed. However, because the object itself isn't fully constructed, the destructor isn't run.

Derived constructors and extended aggregate initialization

If the constructor of a base class is non-public, but accessible to a derived class, then you can't use empty braces to initialize an object of the derived type under /std:c++17 mode and later in Visual Studio 2017 and later.

The following example shows C++14 conformant behavior:

In C++17, Derived is now considered an aggregate type. It means that the initialization of Base via the private default constructor happens directly, as part of the extended aggregate initialization rule. Previously, the Base private constructor was called via the Derived constructor, and it succeeded because of the friend declaration.

The following example shows C++17 behavior in Visual Studio 2017 and later in /std:c++17 mode:

Constructors for classes that have multiple inheritance

If a class is derived from multiple base classes, the base class constructors are invoked in the order in which they're listed in the declaration of the derived class:

You should expect the following output:

  • Delegating constructors

A delegating constructor calls a different constructor in the same class to do some of the work of initialization. This feature is useful when you have multiple constructors that all have to perform similar work. You can write the main logic in one constructor and invoke it from others. In the following trivial example, Box(int) delegates its work to Box(int,int,int):

The object created by the constructors is fully initialized as soon as any constructor is finished. For more information, see Delegating Constructors .

Inheriting constructors (C++11)

A derived class can inherit the constructors from a direct base class by using a using declaration as shown in the following example:

Visual Studio 2017 and later : The using statement in /std:c++17 mode and later brings into scope all constructors from the base class except ones that have an identical signature to constructors in the derived class. In general, it's best to use inheriting constructors when the derived class declares no new data members or constructors.

A class template can inherit all the constructors from a type argument if that type specifies a base class:

A deriving class can't inherit from multiple base classes if those base classes have constructors that have an identical signature.

Constructors and composite classes

Classes that contain class-type members are known as composite classes . When a class-type member of a composite class is created, the constructor is called before the class's own constructor. When a contained class lacks a default constructor, you must use an initialization list in the constructor of the composite class. In the earlier StorageBox example, if you change the type of the m_label member variable to a new Label class, you must call both the base class constructor and initialize the m_label variable in the StorageBox constructor:

In this section

  • Copy constructors and copy assignment operators
  • Move constructors and move assignment operators

Classes and structs

Was this page helpful?

Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback .

Submit and view feedback for

Additional resources

Learn C++

24.4 — Constructors and initialization of derived classes

In the past two lessons, we’ve explored some basics around inheritance in C++ and the order that derived classes are initialized. In this lesson, we’ll take a closer look at the role of constructors in the initialization of derived classes. To do so, we will continue to use the simple Base and Derived classes we developed in the previous lesson:

With non-derived classes, constructors only have to worry about their own members. For example, consider Base. We can create a Base object like this:

Here’s what actually happens when base is instantiated:

  • Memory for base is set aside
  • The appropriate Base constructor is called
  • The member initializer list initializes variables
  • The body of the constructor executes
  • Control is returned to the caller

This is pretty straightforward. With derived classes, things are slightly more complex:

Here’s what actually happens when derived is instantiated:

  • Memory for derived is set aside (enough for both the Base and Derived portions)
  • The appropriate Derived constructor is called
  • The Base object is constructed first using the appropriate Base constructor . If no base constructor is specified, the default constructor will be used.

The only real difference between this case and the non-inherited case is that before the Derived constructor can do anything substantial, the Base constructor is called first. The Base constructor sets up the Base portion of the object, control is returned to the Derived constructor, and the Derived constructor is allowed to finish up its job.

Initializing base class members

One of the current shortcomings of our Derived class as written is that there is no way to initialize m_id when we create a Derived object. What if we want to set both m_cost (from the Derived portion of the object) and m_id (from the Base portion of the object) when we create a Derived object?

New programmers often attempt to solve this problem as follows:

This is a good attempt, and is almost the right idea. We definitely need to add another parameter to our constructor, otherwise C++ will have no way of knowing what value we want to initialize m_id to.

However, C++ prevents classes from initializing inherited member variables in the member initializer list of a constructor. In other words, the value of a member variable can only be set in a member initializer list of a constructor belonging to the same class as the variable.

Why does C++ do this? The answer has to do with const and reference variables. Consider what would happen if m_id were const. Because const variables must be initialized with a value at the time of creation, the base class constructor must set its value when the variable is created. However, when the base class constructor finishes, the derived class constructor’s member initializer lists are then executed. Each derived class would then have the opportunity to initialize that variable, potentially changing its value! By restricting the initialization of variables to the constructor of the class those variables belong to, C++ ensures that all variables are initialized only once.

The end result is that the above example does not work because m_id was inherited from Base, and only non-inherited variables can be initialized in the member initializer list.

However, inherited variables can still have their values changed in the body of the constructor using an assignment. Consequently, new programmers often also try this:

While this actually works in this case, it wouldn’t work if m_id were a const or a reference (because const values and references have to be initialized in the member initializer list of the constructor). It’s also inefficient because m_id gets assigned a value twice: once in the member initializer list of the Base class constructor, and then again in the body of the Derived class constructor. And finally, what if the Base class needed access to this value during construction? It has no way to access it, since it’s not set until the Derived constructor is executed (which pretty much happens last).

So how do we properly initialize m_id when creating a Derived class object?

In all of the examples so far, when we instantiate a Derived class object, the Base class portion has been created using the default Base constructor. Why does it always use the default Base constructor? Because we never told it to do otherwise!

Fortunately, C++ gives us the ability to explicitly choose which Base class constructor will be called! To do this, simply add a call to the Base class constructor in the member initializer list of the derived class:

Now, when we execute this code:

The base class constructor Base(int) will be used to initialize m_id to 5, and the derived class constructor will be used to initialize m_cost to 1.3!

Thus, the program will print:

In more detail, here’s what happens:

  • Memory for derived is allocated.
  • The Derived(double, int) constructor is called, where cost = 1.3, and id = 5.
  • The compiler looks to see if we’ve asked for a particular Base class constructor. We have! So it calls Base(int) with id = 5.
  • The base class constructor member initializer list sets m_id to 5.
  • The base class constructor body executes, which does nothing.
  • The base class constructor returns.
  • The derived class constructor member initializer list sets m_cost to 1.3.
  • The derived class constructor body executes, which does nothing.
  • The derived class constructor returns.

This may seem somewhat complex, but it’s actually very simple. All that’s happening is that the Derived constructor is calling a specific Base constructor to initialize the Base portion of the object. Because m_id lives in the Base portion of the object, the Base constructor is the only constructor that can initialize that value.

Note that it doesn’t matter where in the Derived constructor member initializer list the Base constructor is called -- it will always execute first.

Now we can make our members private

Now that you know how to initialize base class members, there’s no need to keep our member variables public. We make our member variables private again, as they should be.

As a quick refresher, public members can be accessed by anybody. Private members can only be accessed by member functions of the same class. Note that this means derived classes can not access private members of the base class directly! Derived classes will need to use access functions to access private members of the base class.

In the above code, we made m_id and m_cost private. This is fine, since we use the relevant constructors to initialize them, and use a public accessor to get the values.

This prints, as expected:

We’ll talk more about access specifiers in the next lesson.

Another example

Let’s take a look at another pair of classes we’ve previously worked with:

As we’d previously written it, BaseballPlayer only initializes its own members and does not specify a Person constructor to use. This means every BaseballPlayer we create is going to use the default Person constructor, which will initialize the name to blank and age to 0. Because it makes sense to give our BaseballPlayer a name and age when we create them, we should modify this constructor to add those parameters.

Here’s our updated classes that use private members, with the BaseballPlayer class calling the appropriate Person constructor to initialize the inherited Person member variables:

Now we can create baseball players like this:

This outputs:

As you can see, the name and age from the base class were properly initialized, as was the number of home runs and batting average from the derived class.

Inheritance chains

Classes in an inheritance chain work in exactly the same way.

In this example, class C is derived from class B, which is derived from class A. So what happens when we instantiate an object of class C?

First, main() calls C(int, double, char). The C constructor calls B(int, double). The B constructor calls A(int). Because A does not inherit from anybody, this is the first class we’ll construct. A is constructed, prints the value 5, and returns control to B. B is constructed, prints the value 4.3, and returns control to C. C is constructed, prints the value ‘R’, and returns control to main(). And we’re done!

Thus, this program prints:

It is worth mentioning that constructors can only call constructors from their immediate parent/base class. Consequently, the C constructor could not call or pass parameters to the A constructor directly. The C constructor can only call the B constructor (which has the responsibility of calling the A constructor).

Destructors

When a derived class is destroyed, each destructor is called in the reverse order of construction. In the above example, when c is destroyed, the C destructor is called first, then the B destructor, then the A destructor.

If your base class has virtual functions, your destructor should also be virtual, otherwise undefined behavior will result in certain cases. We cover this case in lesson 25.4 -- Virtual destructors, virtual assignment, and overriding virtualization .

When constructing a derived class, the derived class constructor is responsible for determining which base class constructor is called. If no base class constructor is specified, the default base class constructor will be used. In that case, if no default base class constructor can be found (or created by default), the compiler will display an error. The classes are then constructed in order from most base to most derived.

At this point, you now understand enough about C++ inheritance to create your own inherited classes!

  • Let’s implement our Fruit example that we talked about in our introduction to inheritance. Create a Fruit base class that contains two private members: a name (std::string), and a color (std::string). Create an Apple class that inherits Fruit. Apple should have an additional private member: fiber (double). Create a Banana class that also inherits Fruit. Banana has no additional members.

The following program should run:

And print the following:

Hint: Because a and b are const, you’ll need to mind your consts. Make sure your parameters and functions are appropriately const.

Show Solution

guest

  • Sign In / Suggest an Article

Current ISO C++ status

Upcoming ISO C++ meetings

Upcoming C++ conferences

Compiler conformance status

Pure Virtual C++ 2024

April 30, Online  

C++ Now 2024

May 7-12, Aspen, CO, USA

ISO C++ committee meeting

June 24-29, St. Louis, MO, USA

July 2-5, Folkestone, Kent, UK

Constructors

What’s the deal with constructors.

Constructors build objects from dust.

Constructors are like “init functions”. They turn a pile of arbitrary bits into a living object. Minimally they initialize internally used fields. They may also allocate resources (memory, files, semaphores, sockets, etc).

“ctor” is a typical abbreviation for constructor.

Is there any difference between List x; and List x(); ?

A big difference!

Suppose that List is the name of some class. Then function f() declares a local List object called x :

But function g() declares a function called x() that returns a List :

Can one constructor of a class call another constructor of the same class to initialize the this object?

The answer below applies to Classic (pre-11) C++. This question covers the C++11 feature of constructors that call same-type constructors.

Let’s work an example. Suppose you want your constructor Foo::Foo(char) to call another constructor of the same class, say Foo::Foo(char,int) , in order that Foo::Foo(char,int) would help initialize the this object. Unfortunately there’s no way to do this in Classic C++.

Some people do it anyway. Unfortunately it doesn’t do what they want. For example, the line Foo(x, 0); does not call Foo::Foo(char,int) on the this object. Instead it calls Foo::Foo(char,int) to initialize a temporary, local object ( not this ), then it immediately destructs that temporary when control flows over the ; .

You can sometimes combine two constructors via a default parameter:

If that doesn’t work, e.g., if there isn’t an appropriate default parameter that combines the two constructors, sometimes you can share their common code in a private init() member function:

BTW do NOT try to achieve this via placement new . Some people think they can say new(this) Foo(x, int(x)+7) within the body of Foo::Foo(char) . However that is bad, bad, bad. Please don’t write me and tell me that it seems to work on your particular version of your particular compiler; it’s bad. Constructors do a bunch of little magical things behind the scenes, but that bad technique steps on those partially constructed bits. Just say no.

Is the default constructor for Fred always Fred::Fred() ?

A “default constructor” is a constructor that can be called with no arguments. One example of this is a constructor that takes no parameters:

Another example of a “default constructor” is one that can take arguments, provided they are given default values:

Which constructor gets called when I create an array of Fred objects?

Fred ’s default constructor (except as discussed below).

If your class doesn’t have a default constructor , you’ll get a compile-time error when you attempt to create an array using the above simple syntax:

However, even if your class already has a default constructor, you should try to use std::vector<Fred> rather than an array ( arrays are evil ). std::vector lets you decide to use any constructor, not just the default constructor:

Even though you ought to use a std::vector rather than an array, there are times when an array might be the right thing to do, and for those, you might need the “explicit initialization of arrays” syntax. Here’s how:

Of course you don’t have to do Fred(5,7) for every entry — you can put in any numbers you want, even parameters or other variables.

Finally, you can use placement-new to manually initialize the elements of the array. Warning: it’s ugly: the raw array can’t be of type Fred , so you’ll need a bunch of pointer-casts to do things like compute array index operations. Warning: it’s compiler- and hardware-dependent: you’ll need to make sure the storage is aligned with an alignment that is at least as strict as is required for objects of class Fred . Warning: it’s tedious to make it exception-safe: you’ll need to manually destruct the elements, including in the case when an exception is thrown part-way through the loop that calls the constructors. But if you really want to do it anyway, read up on placement-new . (BTW placement-new is the magic that is used inside of std::vector . The complexity of getting everything right is yet another reason to use std::vector .)

By the way, did I ever mention that arrays are evil ? Or did I mention that you ought to use a std::vector unless there is a compelling reason to use an array?

Should my constructors use “initialization lists” or “assignment”?

Initialization lists. In fact, constructors should initialize as a rule all member objects in the initialization list. One exception is discussed further down.

Watch this space for discussion of Non Static Data Member Initialization in C++11

Consider the following constructor that initializes member object x_ using an initialization list: Fred::Fred() : x_( whatever ) { } . The most common benefit of doing this is improved performance. For example, if the expression whatever is the same type as member variable x_ , the result of the whatever expression is constructed directly inside x_ — the compiler does not make a separate copy of the object. Even if the types are not the same, the compiler is usually able to do a better job with initialization lists than with assignments.

The other (inefficient) way to build constructors is via assignment, such as: Fred::Fred() { x_ = whatever ; } . In this case the expression whatever causes a separate, temporary object to be created, and this temporary object is passed into the x_ object’s assignment operator. Then that temporary object is destructed at the ; . That’s inefficient.

As if that wasn’t bad enough, there’s another source of inefficiency when using assignment in a constructor: the member object will get fully constructed by its default constructor, and this might, for example, allocate some default amount of memory or open some default file. All this work could be for naught if the whatever expression and/or assignment operator causes the object to close that file and/or release that memory (e.g., if the default constructor didn’t allocate a large enough pool of memory or if it opened the wrong file).

Conclusion: All other things being equal, your code will run faster if you use initialization lists rather than assignment.

Note: There is no performance difference if the type of x_ is some built-in/intrinsic type, such as int or char* or float . But even in these cases, my personal preference is to set those data members in the initialization list rather than via assignment for consistency. Another symmetry argument in favor of using initialization lists even for built-in/intrinsic types: non-static const and non-static reference data members can’t be assigned a value in the constructor, so for symmetry it makes sense to initialize everything in the initialization list.

Now for the exceptions. Every rule has exceptions (hmmm; does “every rule has exceptions” have exceptions? reminds me of Gödel’s Incompleteness Theorems), and there are a couple of exceptions to the “use initialization lists” rule. Bottom line is to use common sense: if it’s cheaper, better, faster, etc. to not use them, then by all means, don’t use them. This might happen when your class has two constructors that need to initialize the this object’s data members in different orders. Or it might happen when two data members are self-referential. Or when a data-member needs a reference to the this object, and you want to avoid a compiler warning about using the this keyword prior to the { that begins the constructor’s body (when your particular compiler happens to issue that particular warning). Or when you need to do an if … throw test on a variable (parameter, global, etc.) prior to using that variable to initialize one of your this members. This list is not exhaustive; please don’t write me asking me to add another “Or when…”. The point is simply this: use common sense.

How should initializers be ordered in a constructor’s initialization list?

Immediate base classes (left to right), then member objects (top to bottom).

In other words, the order of the initialization list should mimic the order in which initializations will take place. This guideline discourages a particularly subtle class of order dependency errors by giving an obvious, visual clue. For example, the following contains a hideous error.

The output of this program follows.

Note that y_ is used ( Y::f() ) before it is initialized ( Y::Y() ). If instead the programmer had read and abided by the guideline in this FAQ, the error would be more obvious: the initialization list of Z::Z() would have read x_(y_), y_() , visually indicating that y_ was being used before being initialized.

Not all compilers issue diagnostic messages for these cases. You have been warned.

Is it moral for one member object to be initialized using another member object in the initializer expression?

Yes, but use care and do that only when it adds value.

In a constructor’s initialization list, it is easiest and safest to avoid using one member object from this object in the initialization expression of a subsequent initializer for this object. This guideline prevents subtle order-dependency errors if someone reorganizes the layout of member objects within the class .

Because of this guideline, the constructor that follows uses s.len_ + 1u rather than len_ + 1u , even though they are otherwise equivalent. The s. prefix avoids an unnecessary and avoidable order dependency.

An unnecessary order dependency on the class layout of len_ and data_ would have been introduced if the constructor’s initialization of data_ had used len_ + 1u rather than s.len_ + 1u . However using len_ within a constructor body ( {...} ) is okay. No order dependency is introduced since the entire initialization list is guaranteed to finish before the constructor body begins executing.

What if one member object has to be initialized using another member object?

Comment the declaration of the effected data members with //ORDER DEPENDENCY .

If a constructor initializes a member object of this object using another member object of this object, rearranging the data members of the class could break the constructor . This important maintenance constraint should be documented in the class body.

For example, in the constructor below, the initializer for data_ uses len_ to avoid a redundant call to std::strlen(s) , which introduces an order dependency in the class body.

Note that the //ORDER DEPENDENCY comment is listed with the effected data members in the class body , not with the constructor initialization list where the order dependency was actually created. That is because the order of member objects in the class body is critical; the order of initializers in the constructor initialization list is irrelevant .

Should you use the this pointer in the constructor?

Some people feel you should not use the this pointer in a constructor because the object is not fully formed yet. However you can use this in the constructor (in the { body } and even in the initialization list ) if you are careful.

Here is something that always works: the { body } of a constructor (or a function called from the constructor) can reliably access the data members declared in a base class and/or the data members declared in the constructor’s own class. This is because all those data members are guaranteed to have been fully constructed by the time the constructor’s { body } starts executing.

Here is something that never works: the { body } of a constructor (or a function called from the constructor) can not get down to a derived class by calling a virtual member function that is overridden in the derived class. If your goal was to get to the overridden function in the derived class, you won’t get what you want . Note that you won’t get to the override in the derived class independent of how you call the virtual member function: explicitly using the this pointer (e.g., this->method() ), implicitly using the this pointer (e.g., method() ), or even calling some other function that calls the virtual member function on your this object. The bottom line is this: even if the caller is constructing an object of a derived class, during the constructor of the base class, your object is not yet of that derived class . You have been warned.

Here is something that sometimes works: if you pass any of the data members in this object to another data member’s initializer , you must make sure that the other data member has already been initialized. The good news is that you can determine whether the other data member has (or has not) been initialized using some straightforward language rules that are independent of the particular compiler you’re using. The bad news is that you have to know those language rules (e.g., base class sub-objects are initialized first (look up the order if you have multiple and/or virtual inheritance!), then data members defined in the class are initialized in the order in which they appear in the class declaration). If you don’t know these rules, then don’t pass any data member from the this object (regardless of whether or not you explicitly use the this keyword) to any other data member’s initializer ! And if you do know the rules, please be careful.

What is the “Named Constructor Idiom”?

A technique that provides more intuitive and/or safer construction operations for users of your class.

The problem is that constructors always have the same name as the class. Therefore the only way to differentiate between the various constructors of a class is by the parameter list. But if there are lots of constructors, the differences between them become somewhat subtle and error prone.

With the Named Constructor Idiom, you declare all the class’s constructors in the private or protected sections, and you provide public static methods that return an object. These static methods are the so-called “Named Constructors.” In general there is one such static method for each different way to construct an object.

For example, suppose we are building a Point class that represents a position on the X-Y plane. Turns out there are two common ways to specify a 2-space coordinate: rectangular coordinates (X+Y), polar coordinates (Radius+Angle). (Don’t worry if you can’t remember these; the point isn’t the particulars of coordinate systems; the point is that there are several ways to create a Point object.) Unfortunately the parameters for these two coordinate systems are the same: two float s. This would create an ambiguity error in the overloaded constructors:

One way to solve this ambiguity is to use the Named Constructor Idiom:

Now the users of Point have a clear and unambiguous syntax for creating Point s in either coordinate system:

Make sure your constructors are in the protected section if you expect Point to have derived classes.

The Named Constructor Idiom can also be used to make sure your objects are always created via new .

Note that the Named Constructor Idiom, at least as implemented above, is just as fast as directly calling a constructor — modern compilers will not make any extra copies of your object .

Does return-by-value mean extra copies and extra overhead?

Not necessarily.

All(?) commercial-grade compilers optimize away the extra copy, at least in cases as illustrated in the previous FAQ .

To keep the example clean, let’s strip things down to the bare essentials. Suppose function caller() calls rbv() (“rbv” stands for “return by value”) which returns a Foo object by value:

Now the question is, How many Foo objects will there be? Will rbv() create a temporary Foo object that gets copy-constructed into x ? How many temporaries? Said another way, does return-by-value necessarily degrade performance?

The point of this FAQ is that the answer is No, commercial-grade C++ compilers implement return-by-value in a way that lets them eliminate the overhead, at least in simple cases like those shown in the previous FAQ. In particular, all(?) commercial-grade C++ compilers will optimize this case:

Certainly the compiler is allowed to create a temporary, local Foo object, then copy-construct that temporary into variable x within caller() , then destruct the temporary. But all(?) commercial-grade C++ compilers won’t do that: the return statement will directly construct x itself. Not a copy of x , not a pointer to x , not a reference to x , but x itself.

You can stop here if you don’t want to genuinely understand the previous paragraph, but if you want to know the secret sauce (so you can, for example, reliably predict when the compiler can and cannot provide that optimization for you), the key is to know that compilers usually implement return-by-value using pass-by-pointer. When caller() calls rbv() , the compiler secretly passes a pointer to the location where rbv() is supposed to construct the “returned” object. It might look something like this (it’s shown as a void* rather than a Foo* since the Foo object has not yet been constructed):

So the first ingredient in the secret sauce is that the compiler (usually) transforms return-by-value into pass-by-pointer. This means that commercial-grade compilers don’t bother creating a temporary: they directly construct the returned object in the location pointed to by put_result_here .

The second ingredient in the secret sauce is that compilers typically implement constructors using a similar technique. This is compiler-dependent and somewhat idealized (I’m intentionally ignoring how to handle new and overloading), but compilers typically implement Foo::Foo(int a, int b) using something like this:

Putting these together, the compiler might implement the return statement in rbv() by simply passing put_result_here as the constructor’s this pointer:

So caller() passes &x to rbv() , and rbv() in turn passes &x to the constructor (as the this pointer). That means constructor directly constructs x .

In the early 90s I did a seminar for IBM’s compiler group in Toronto, and one of their engineers told me that they found this return-by-value optimization to be so fast that you get it even if you don’t compile with optimization turned on. Because the return-by-value optimization causes the compiler to generate less code, it actually improves compile-times in addition to making your generated code smaller and faster. The point is that the return-by-value optimization is almost universally implemented, at least in code cases like those shown above.

Final thought: this discussion was limited to whether there will be any extra copies of the returned object in a return-by-value call. Don’t confuse that with other things that could happen in caller() . For example, if you changed caller() from Foo x = rbv(); to Foo x; x = rbv(); (note the ; after the declaration), the compiler is required to use Foo ’s assignment operator, and unless the compiler can prove that Foo ’s default constructor followed by assignment operator is exactly the same as its copy constructor, the compiler is required by the language to put the returned object into an unnamed temporary within caller() , use the assignment operator to copy the temporary into x , then destruct the temporary. The return-by-value optimization still plays its part since there will be only one temporary, but by changing Foo x = rbv(); to Foo x; x = rbv(); , you have prevented the compiler from eliminating that last temporary.

What about returning a local variable by value? Does the local exist as a separate object, or does it get optimized away?

When your code returns a local variable by value, your compiler might optimize away the local variable completely - zero space-cost and zero time-cost - the local variable never actually exists as a distinct object from the caller’s target variable (see below for specifics about exactly what this means). Other compilers do not optimize it away.

These are some(!) of the compilers that optimize away the local variable completely:

  • GNU C++ (g++) since at least version 3.3.3
  • (Others need to be added; need more info)

These are some(!) of the compilers that do not optimize away the local variable:

  • Microsoft Visual C++.NET 2003

Here is an example showing what we mean in this FAQ:

The question addressed in this FAQ is this: How many Foo objects actually get created in the runtime system? Conceptually there could be as many as three distinct objects: the temporary created by Foo(42, 73) , variable y (in rbv() ), and variable x (in caller() ). However as we saw earlier most compilers merge Foo(42, 73) and variable y into the same object, reducing the total number of objects from 3 to 2. But this FAQ pushes it one step further: does y (in rbv() ) show up as a distinct, runtime object from x (in caller() )?

Some compilers, including but not limited to those listed above, completely optimize away local variable y . In those compilers, there is only one Foo object in the above code: caller() ’s variable x is exactly identically the same object as rbv() ’s variable y .

They do this the same way as described earlier : the return-by-value in function rbv() is implemented as pass-by-pointer, where the pointer points to the location where the returned object is to be initialized.

So instead of constructing y as a local object, these compilers simply construct *put_result_here , and everytime they see variable y used in the original source code, they substitute *put_result_here instead. Then the line return y; becomes simply return; since the returned object has already been constructed in the location designated by the caller .

Here is the resulting (pseudo)code:

Caveat: this optimization can be applied only when all a function’s return statements return the same local variable. If one return statement in rbv() returned local variable y but another returned something else, such as a global or a temporary, the compiler could not alias the local variable into the caller’s destination, x . Verifying that all the function’s return statements return the same local variable requires extra work on the part of the compiler writers, which is usually why some compilers fail to implement that return-local-by-value optimization.

Why can’t I initialize my static member data in my constructor’s initialization list?

Because you must explicitly define your class’s static data members.

Fred.cpp (or Fred.C or whatever):

Note: in some cases, the definition of Fred::j_ might not contain the = initializer part. For details, see here and here .

Why are classes with static data members getting linker errors?

Because static data members must be explicitly defined in exactly one compilation unit . If you didn’t do this, you’ll probably get an "undefined external" linker error. For example:

The linker will holler at you ( "Fred::j_ is not defined" ) unless you define (as opposed to merely declare) Fred::j_ in (exactly) one of your source files:

The usual place to define static data members of class Fred is file Fred.cpp (or Fred.C or whatever source file extension you use).

Note: in some cases, you can add = initializer ; to the declaration of class-scope static declarations , however if you ever use the data member, you still need to explicitly define it in exactly one compilation unit. In this case you don’t include an = initializer in the definition. A separate FAQ covers this topic.

Can I add = initializer ; to the declaration of a class-scope static const data member?

Yes, though with some important caveats.

Before going through the caveats, here is a simple example that is allowed:

And, just like other static data members , it must be defined in exactly one compilation unit, though this time without the = initializer part:

The caveats are that you may do this only with integral or enumeration types, and that the initializer expression must be an expression that can be evaluated at compile-time: it must only contain other constants, possibly combined with built-in operators. For example, 3*4 is a compile-time constant expression, as is a*b provided a and b are compile-time constants. After the declaration above, Fred::maximum is also a compile-time constant: it can be used in other compile-time constant expressions.

If you ever take the address of Fred::maximum , such as passing it by reference or explicitly saying &Fred::maximum , the compiler will make sure it has a unique address. If not, Fred::maximum won’t even take up space in your process’s static data area.

What’s the “ static initialization order ‘fiasco’ (problem)”?

A subtle way to crash your program.

The static initialization order problem is a very subtle and commonly misunderstood aspect of C++. Unfortunately it’s very hard to detect — the errors often occur before main() begins.

In short, suppose you have two static objects x and y which exist in separate source files, say x.cpp and y.cpp . Suppose further that the initialization for the y object (typically the y object’s constructor) calls some method on the x object.

That’s it. It’s that simple.

The tough part is that you have a 50%-50% chance of corrupting the program. If the compilation unit for x.cpp happens to get initialized first, all is well. But if the compilation unit for y.cpp get initialized first, then y ’s initialization will get run before x ’s initialization, and you’re toast. E.g., y ’s constructor could call a method on the x object, yet the x object hasn’t yet been constructed.

For how to address the problem, see the next FAQ .

Note: The static initialization order problem can also, in some cases , apply to built-in/intrinsic types.

How do I prevent the “ static initialization order problem”?

To prevent the static initialization order problem , use the Construct On First Use Idiom , described below.

The basic idea of the Construct On First Use Idiom is to wrap your static object inside a function. For example, suppose you have two classes, Fred and Barney . There is a namespace-scope / global Fred object called x , and a namespace-scope / global Barney object called y . Barney ’s constructor invokes the goBowling() method on the x object. The file x.cpp defines the x object:

The file y.cpp defines the y object:

For completeness the Barney constructor might look something like this:

You would have a static initialization disaster if y got constructed before x . As written above, this disaster would occur roughly 50% of the time, since the two objects are declared in different source files and those source files give no hints to the compiler or linker as to the order of static initialization.

There are many solutions to this problem, but a very simple and completely portable solution is the Construct On First Use Idiom : replace the namespace-scope / global Fred object x with a namespace-scope / global function x() that returns the Fred object by reference.

Since static local objects are constructed the first time control flows over their declaration (only), the above new Fred() statement will only happen once: the first time x() is called. Every subsequent call will return the same Fred object (the one pointed to by ans ). Then all you do is change your usages of x to x() :

This is called the Construct On First Use Idiom because it does just that: the (logically namespace-scope / global) Fred object is constructed on its first use.

The downside of this approach is that the Fred object is never destructed. If the Fred object has a destructor with important side effects, there is another technique that answers this concern; but it needs to be used with care since it creates the possibility of another (equally nasty) problem.

Why doesn’t the Construct On First Use Idiom use a static object instead of a static pointer?

Short answer: it’s possible to use a static object rather than a static pointer , but doing so opens up another (equally subtle, equally nasty) problem.

Long answer: sometimes people worry about the fact that the previous solution “leaks.” In many cases, this is not a problem, but it is a problem in some cases. Note: even though the object pointed to by ans in the previous FAQ is never deleted, the memory doesn’t actually “leak” when the program exits since the operating system automatically reclaims all the memory in a program’s heap when that program exits. In other words, the only time you’d need to worry about this is when the destructor for the Fred object performs some important action (such as writing something to a file) that must occur sometime while the program is exiting.

In those cases where the construct-on-first-use object (the Fred , in this case) needs to eventually get destructed, you might consider changing function x() as follows:

However there is (or rather, may be) a rather subtle problem with this change. To understand this potential problem, let’s remember why we’re doing all this in the first place: we need to make 100% sure our static object (a) gets constructed prior to its first use and (b) doesn’t get destructed until after its last use. Obviously it would be a disaster if any static object got used either before construction or after destruction. The message here is that you need to worry about two situations (static initialization and static deinitialization), not just one.

By changing the declaration from static Fred* ans = new Fred(); to static Fred ans; , we still correctly handle the initialization situation but we no longer handle the deinitialization situation. For example, if there are 3 static objects, say a , b and c , that use ans during their destructors, the only way to avoid a static deinitialization disaster is if ans is destructed after all three.

The point is simple: if there are any other static objects whose destructors might use ans after ans is destructed, bang, you’re dead. If the constructors of a , b and c use ans , you should normally be okay since the runtime system will, during static deinitialization, destruct ans after the last of those three objects is destructed. However if a and/or b and/or c fail to use ans in their constructors and/or if any code anywhere gets the address of ans and hands it to some other static object, all bets are off and you have to be very, very careful.

There is a third approach that handles both the static initialization and static deinitialization situations , but it has other non-trivial costs.

What is a technique to guarantee both static initialization and static deinitialization?

Short answer: use the Nifty Counter Idiom (but make sure you understand the non-trivial tradeoffs!).

Motivation:

  • The Construct On First Use Idiom uses a pointer and intentionally leaks the object. That is often innocuous, since the operating system will typically clean up a process’s memory when the process terminates. However if the object has a non-trivial destructor with important side effects, such as writing to a file or some other non-volatile action, then you need more.
  • That’s where the second version of the Construct On First Use Idiom came in: it doesn’t leak the object, but it does not control the order of static deinitialization, so it is (very!) unsafe to use the object during static deinitialization, that is, from a destructor of another statically declared object.
  • If you need to control the order of both static initialization and static deinitialization, meaning if you wish to access a statically allocated object from both constructors and destructors of other static objects, then keep reading.
  • Otherwise run away.

TODO: WRITE THIS UP

TODO: WRITE UP TRADEOFFS — now that you know how to use the Nifty Counter Idiom , be sure you understand both when and (especially!) when not to use it! One size does not fit all.

How do I prevent the “ static initialization order problem” for my static data members?

Use the Construct Members On First Use Idiom , which is basically the same as the regular Construct On First Use Idiom , or perhaps one of its variants , but it uses a static member function instead of a namespace-scope / global function.

Suppose you have a class X that has a static Fred object:

Naturally this static member is initialized separately:

Naturally also the Fred object will be used in one or more of X ’s methods:

But now the “disaster scenario” is if someone somewhere somehow calls this method before the Fred object gets constructed. For example, if someone else creates a static X object and invokes its someMethod() method during static initialization, then you’re at the mercy of the compiler as to whether the compiler will construct X::x_ before or after the someMethod() is called. (Note that the ANSI/ISO C++ committee is working on this problem, but compilers aren’t yet generally available that handle these changes; watch this space for an update in the future.)

In any event, it’s always portable and safe to change the X::x_ static data member into a static member function:

Then you simply change any usages of x_ to x() :

If you’re super performance sensitive and you’re concerned about the overhead of an extra function call on each invocation of X::someMethod() you can set up a static Fred& instead. As you recall, static local are only initialized once (the first time control flows over their declaration), so this will call X::x() only once: the first time X::someMethod() is called:

Do I need to worry about the “ static initialization order problem” for variables of built-in/intrinsic types?

If you initialize your built-in/intrinsic type using a function call, the static initialization order problem is able to kill you just as bad as with user-defined/class types. For example, the following code shows the failure:

The output of this little program will show that it uses y before initializing it. The solution, as before, is the Construct On First Use Idiom :

Of course you might be able to simplify this by moving the initialization code for x and y into their respective functions:

And, if you can get rid of the print statements you can further simplify these to something really simple:

Furthermore, since y is initialized using a constant expression, it no longer needs its wrapper function — it can be a simple variable again.

How can I handle a constructor that fails?

Throw an exception. For details, see here .

What is the “Named Parameter Idiom”?

It’s a fairly useful way to exploit method chaining .

The fundamental problem solved by the Named Parameter Idiom is that C++ only supports positional parameters . For example, a caller of a function isn’t allowed to say, “Here’s the value for formal parameter xyz , and this other thing is the value for formal parameter pqr .” All you can do in C++ (and C and Java) is say, “Here’s the first parameter, here’s the second parameter, etc.” The alternative, called named parameters and implemented in the language Ada, is especially useful if a function takes a large number of mostly default-able parameters.

Over the years people have cooked up lots of workarounds for the lack of named parameters in C and C++. One of these involves burying the parameter values in a string parameter then parsing this string at run-time. This is what’s done in the second parameter of fopen() , for example. Another workaround is to combine all the boolean parameters in a bit-map, then the caller or ’s a bunch of bit-shifted constants together to produce the actual parameter. This is what’s done in the second parameter of open() , for example. These approaches work, but the following technique produces caller-code that’s more obvious, easier to write, easier to read, and is generally more elegant.

The idea, called the Named Parameter Idiom, is to change the function’s parameters to methods of a newly created class, where all these methods return *this by reference. Then you simply rename the main function into a parameterless “do-it” method on that class.

We’ll work an example to make the previous paragraph easier to understand.

The example will be for the “open a file” concept. Let’s say that concept logically requires a parameter for the file’s name, and optionally allows parameters for whether the file should be opened read-only vs. read-write vs. write-only, whether or not the file should be created if it doesn’t already exist, whether the writing location should be at the end (“append”) or the beginning (“overwrite”), the block-size if the file is to be created, whether the I/O is buffered or non-buffered, the buffer-size, whether it is to be shared vs. exclusive access, and probably a few others. If we implemented this concept using a normal function with positional parameters, the caller code would be very difficult to read: there’d be as many as 8 positional parameters, and the caller would probably make a lot of mistakes. So instead we use the Named Parameter Idiom.

Before we go through the implementation, here’s what the caller code might look like, assuming you are willing to accept all the function’s default parameters:

That’s the easy case. Now here’s what it might look like if you want to change a bunch of the parameters.

Notice how the “parameters”, if it’s fair to call them that, are in random order (they’re not positional) and they all have names. So the programmer doesn’t have to remember the order of the parameters, and the names are (hopefully) obvious.

So here’s how to implement it: first we create a class ( OpenFile ) that houses all the parameter values as private data members. The required parameters (in this case, the only required parameter is the file’s name) is implemented as a normal, positional parameter on OpenFile ’s constructor, but that constructor doesn’t actually open the file. Then all the optional parameters (readonly vs. readwrite, etc.) become methods. These methods (e.g., readonly() , blockSize(unsigned) , etc.) return a reference to their this object so the method calls can be chained .

The only other thing to do is make the constructor for class File to take an OpenFile object:

This constructor gets the actual parameters from the OpenFile object, then actually opens the file:

Note that OpenFile declares File as its friend , that way OpenFile doesn’t need a bunch of (otherwise useless) public: get methods .

Since each member function in the chain returns a reference, there is no copying of objects and the chain is highly efficient. Furthermore, if the various member functions are inline , the generated object code will probably be on par with C-style code that sets various members of a struct . Of course if the member functions are not inline , there may be a slight increase in code size and a slight decrease in performance (but only if the construction occurs on the critical path of a CPU-bound program; this is a can of worms I’ll try to avoid opening), so it may, in this case, be a tradeoff for making the code more reliable.

Why am I getting an error after declaring a Foo object via Foo x(Bar()) ?

Because that doesn’t create a Foo object - it declares a non-member function that returns a Foo object. The term “Most Vexing Parse” was coined by Scott Myers to describe this situation.

This is really going to hurt; you might want to sit down.

First, here’s a better explanation of the problem. Suppose there is a class called Bar that has a default ctor. This might even be a library class such as std::string , but for now we’ll just call it Bar :

Now suppose there’s another class called Foo that has a ctor that takes a Bar . As before, this might be defined by someone other than you.

Now you want to create a Foo object using a temporary Bar . In other words, you want to create an object via Bar() , and pass that to the Foo ctor to create a local Foo object called x :

It’s a long story, but one solution (hope you’re sitting down!) is to add an extra pair of () s around the Bar() part:

Another solution is to use = in your declaration (see the fine print below):

Note: The above solution requires yourCode() to be able to access the Foo copy constructor. In most situations that means the Foo copy constructor needs to be public , though it needn’t be public in the less common case where yourCode() is a friend of class Foo . If you’re not sure what any of that means, try it: if your code compiles, you passed the test.

Here’s another solution (more fine print below):

Note: The word “usually” in the above means this: the above fails only when Foo::Foo(const Bar&) constructor is explicit , or when Foo ’s copy constructor is inaccessible (typically when it is private or protected , and your code is not a friend ). If you’re not sure what any of that means, take 60 seconds and compile it. You are guaranteed to find out whether it works or fails at compile-time, so if it compiles cleanly, it will work at runtime.

However, the best solution, the creation of which was at least partially motivated by the fact that this FAQ exists, is to use uniform initialization , which replaces the () around the Bar() call with {} instead.

That’s the end of the solutions; the rest of this is about why this is needed (this is optional; you can skip this section if you don’t care enough about your career to actually understand what’s going on; ha ha): When the compiler sees Foo x(Bar()) , it thinks that the Bar() part is declaring a non-member function that returns a Bar object, so it thinks you are declaring the existence of a function called x that returns a Foo and that takes as a single parameter of type “non-member function that takes nothing and returns a Bar .”

Now here’s the sad part. In fact it’s pathetic. Some mindless drone out there is going to skip that last paragraph, then they’re going to impose a bizarre, incorrect, irrelevant, and just plain stupid coding standard that says something like, “Never create temporaries using a default constructor” or “Always use = in all initializations” or something else equally inane. If that’s you, please fire yourself before you do any more damage. Those who don’t understand the problem shouldn’t tell others how to solve it. Harumph.

(That was mostly tongue in cheek. But there’s a grain of truth in it. The real problem is that people tend to worship consistency, and they tend to extrapolate from the obscure to the common. That’s not wise.)

What is the purpose of the explicit keyword?

The explicit keyword is an optional decoration for constructors and conversion operators to tell the compiler that a certain constructor or conversion operator may not be used to implicitly cast an expression to its class type.

For example, without the explicit keyword the following code is valid:

But sometimes you want to prevent this sort of implicit promotion or implicit type conversion. For example, if Foo is really an array-like container and 42 is the initial size, you might want to let your users say, Foo x(42); or perhaps Foo x = Foo(42); , but not just Foo x = 42; . If that’s the case, you should use the explicit keyword:

You can mix explicit and non- explicit constructors and conversion operators in the same class. For example, this class has an explicit constructor taking a bool but a non- explicit constructor taking a double , and can be implicitly converted to double, but only explicitly converted to bool:

The above code will print the following:

Variable a is initialized using the Foo(double) constructor because Foo(bool) cannot be used in an implicit cast, but true can be interpreted as a (double)true , that is, as 1.0 , and implicitly cast to Foo using Foo::Foo(double) . This may or may not be what you intended, but this is what happens.

Why doesn’t my constructor work right?

This is a question that comes in many forms. Such as:

  • Why does the compiler copy my objects when I don’t want it to?
  • How do I turn off copying?
  • How do I stop implicit conversions?
  • How did my int turn into a complex number?

By default a class is given a copy constructor and a copy assignment that copy all elements, and a move constructor and a move assignment that move all elements. For example:

Here we get p2.x==p1.x and p2.y==p1.y . That’s often exactly what you want (and essential for C compatibility), but consider:

Here, the default copy gives us h2.name==h1.name and h2.p==h1.p . This leads to disaster: when we exit f() the destructors for h1 and h2 are invoked and the object pointed to by h1.p and h2.p is deleted twice.

How do we avoid this? The simplest solution is to mark the operations that copy as deleted:

If we need to copy or move, we can of course define the proper initializers and assignments to provide the desired semantics.

Now return to Point . For Point the default copy semantics is fine, the problem is the constructor:

People provide default arguments to get the convenience used for orig and p1 . Then, some are surprised by the conversion of 2 to Point(2,0) in the call of f() . This constructor defines a conversion. By default that’s an implicit conversion. To require such a conversion to be explicit, declare the constructor explicit :

Please Login to submit a recommendation.

If you don’t have an account, you can register for free.

Constructors and member initializer lists

Constructor is a special non-static member function of a class that is used to initialize objects of its class type.

In the definition of a constructor of a class, member initializer list specifies the initializers for direct and virtual base subobjects and non-static data members. ( Not to be confused with std::initializer_list )

Constructors are declared using member function declarators of the following form:

Where class-name must name the current class (or current instantiation of a class template), or, when declared at namespace scope or in a friend declaration, it must be a qualified class name.

The only specifiers allowed in the decl-specifier-seq of a constructor declaration are friend , inline , explicit and constexpr (in particular, no return type is allowed). Note that cv- and ref-qualifiers are not allowed either; const and volatile semantics of an object under construction don't kick in until the most-derived constructor completes.

The body of a function definition of any constructor, before the opening brace of the compound statement, may include the member initializer list , whose syntax is the colon character : , followed by the comma-separated list of one or more member-initializers , each of which has the following syntax

Explanation

Constructors have no names and cannot be called directly. They are invoked when initialization takes place, and they are selected according to the rules of initialization. The constructors without explicit specifier are converting constructors . The constructors with a constexpr specifier make their type a LiteralType . Constructors that may be called without any argument are default constructors . Constructors that take another object of the same type as the argument are copy constructors and move constructors .

Before the compound statement that forms the function body of the constructor begins executing, initialization of all direct bases, virtual bases, and non-static data members is finished. Member initializer list is the place where non-default initialization of these objects can be specified. For members that cannot be default-initialized, such as members of reference and const-qualified types, member initializers must be specified. No initialization is performed for anonymous unions or variant members that do not have a member initializer.

The initializers where class-or-identifier names a virtual base class are ignored during execution of constructors of any class that is not the most derived class of the object that's being constructed.

Names that appear in expression-list or brace-init-list are evaluated in scope of the constructor:

Exceptions that are thrown from member initializers may be handled by function-try-block

Member functions (including virtual member functions) can be called from member initializers, but the behavior is undefined if not all direct bases are initialized at that point.

For virtual calls (if the bases are initialized), the same rules apply as the rules for the virtual calls from constructors and destructors: virtual member functions behave as if the dynamic type of * this is the class that's being constructed (dynamic dispatch does not propagate down the inheritance hierarchy) and virtual calls (but not static calls) to pure virtual member functions are undefined behavior.

Initialization order

The order of member initializers in the list is irrelevant: the actual order of initialization is as follows:

(Note: if initialization order was controlled by the appearance in the member initializer lists of different constructors, then the destructor wouldn't be able to ensure that the order of destruction is the reverse of the order of construction)

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

  • C++11 standard (ISO/IEC 14882:2011):
  • 12.1 Constructors [class.ctor]
  • 12.6.2 Initializing bases and members [class.base.init]
  • C++98 standard (ISO/IEC 14882:1998):
  • Building C++ Classes
  • C++ Prerequisites
  • C++ Requirements
  • C++ Expectations
  • Different CPlus Compilers
  • Coding Standards
  • OOP Encapsulation
  • OO Programming
  • Type Extensibility
  • Encapsulation Packing Data
  • C++ Class Concept
  • Object Class Concept
  • Declare Member Function
  • Using Member Function
  • Private Public Access
  • ADT Interface
  • Black Box Principle
  • Design C++ Class
  • Class vs. Struct
  • OOP Conclusion
  • OOP Encapsulation - Quiz
  • C++ Class Constructs
  • Scope Resolution Operator
  • Unary Form Scope Resolution
  • Binary Scope Resolution
  • Orthogonal Class Design
  • Overloading Member Functions
  • External Member Functions
  • Constructor Functions
  • Variable Memory Allocation
  • Destructor Functions
  • Constructor Destructor
  • Initialization Constructor
  • Constructor Object Declaration
  • Default Constructor
  • Constructor Initializer List
  • Constructors As Conversions
  • C++ Constructor Function
  • Cplus Constructor - Quiz
  • Dynamic Stack
  • Default Copy Constructors
  • Dynamic Structures

Initialization versus Assignment in C++

  • When one object explicitly initializes another, such as in a declaration,
  • When a copy of an object is made to be passed to a function, or
  • When a temporary object is generated (most commonly, as a return value).
  • C++ Classes and Objects
  • C++ Polymorphism

C++ Inheritance

  • C++ Abstraction
  • C++ Encapsulation
  • C++ OOPs Interview Questions
  • C++ OOPs MCQ

C++ Interview Questions

C++ function overloading.

  • C++ Programs
  • C++ Preprocessor

C++ Templates

  • C++ Programming Language

C++ Overview

  • Introduction to C++ Programming Language
  • Features of C++
  • History of C++
  • Interesting Facts about C++
  • Setting up C++ Development Environment
  • Difference between C and C++
  • Writing First C++ Program - Hello World Example
  • C++ Basic Syntax
  • C++ Comments
  • Tokens in C
  • C++ Keywords
  • Difference between Keyword and Identifier

C++ Variables and Constants

  • C++ Variables
  • Constants in C
  • Scope of Variables in C++
  • Storage Classes in C++ with Examples
  • Static Keyword in C++

C++ Data Types and Literals

  • C++ Data Types
  • Literals in C
  • Derived Data Types in C++
  • User Defined Data Types in C++
  • Data Type Ranges and their macros in C++
  • C++ Type Modifiers
  • Type Conversion in C++
  • Casting Operators in C++

C++ Operators

  • Operators in C++
  • C++ Arithmetic Operators
  • Unary operators in C
  • Bitwise Operators in C
  • Assignment Operators in C
  • C++ sizeof Operator
  • Scope resolution operator in C++

C++ Input/Output

  • Basic Input / Output in C++
  • cout in C++
  • cerr - Standard Error Stream Object in C++
  • Manipulators in C++ with Examples

C++ Control Statements

  • Decision Making in C (if , if..else, Nested if, if-else-if )
  • C++ if Statement
  • C++ if else Statement
  • C++ if else if Ladder
  • Switch Statement in C++
  • Jump statements in C++
  • for Loop in C++
  • Range-based for loop in C++
  • C++ While Loop
  • C++ Do/While Loop

C++ Functions

  • Functions in C++
  • return statement in C++ with Examples
  • Parameter Passing Techniques in C
  • Difference Between Call by Value and Call by Reference in C
  • Default Arguments in C++
  • Inline Functions in C++
  • Lambda expression in C++

C++ Pointers and References

  • Pointers and References in C++
  • C++ Pointers
  • Dangling, Void , Null and Wild Pointers in C
  • Applications of Pointers in C
  • Understanding nullptr in C++
  • References in C++
  • Can References Refer to Invalid Location in C++?
  • Pointers vs References in C++
  • Passing By Pointer vs Passing By Reference in C++
  • When do we pass arguments by pointer?
  • Variable Length Arrays (VLAs) in C
  • Pointer to an Array | Array Pointer
  • How to print size of array parameter in C++?
  • Pass Array to Functions in C
  • What is Array Decay in C++? How can it be prevented?

C++ Strings

  • Strings in C++
  • std::string class in C++
  • Array of Strings in C++ - 5 Different Ways to Create
  • String Concatenation in C++
  • Tokenizing a string in C++
  • Substring in C++

C++ Structures and Unions

  • Structures, Unions and Enumerations in C++
  • Structures in C++
  • C++ - Pointer to Structure
  • Self Referential Structures
  • Difference Between C Structures and C++ Structures
  • Enumeration in C++
  • typedef in C++
  • Array of Structures vs Array within a Structure in C

C++ Dynamic Memory Management

  • Dynamic Memory Allocation in C using malloc(), calloc(), free() and realloc()
  • new and delete Operators in C++ For Dynamic Memory
  • new vs malloc() and free() vs delete in C++
  • What is Memory Leak? How can we avoid?
  • Difference between Static and Dynamic Memory Allocation in C

C++ Object-Oriented Programming

  • Object Oriented Programming in C++
  • Access Modifiers in C++
  • Friend Class and Function in C++

Constructors in C++

  • Default Constructors in C++
  • Copy Constructor in C++
  • Destructors in C++
  • Private Destructor in C++
  • When is a Copy Constructor Called in C++?
  • Shallow Copy and Deep Copy in C++
  • When Should We Write Our Own Copy Constructor in C++?
  • Does C++ compiler create default constructor when we write our own?
  • C++ Static Data Members
  • Static Member Function in C++
  • 'this' pointer in C++
  • Scope Resolution Operator vs this pointer in C++
  • Local Classes in C++
  • Nested Classes in C++
  • Enum Classes in C++ and Their Advantage over Enum DataType
  • Difference Between Structure and Class in C++
  • Why C++ is partially Object Oriented Language?

C++ Encapsulation and Abstraction

  • Encapsulation in C++
  • Abstraction in C++
  • Difference between Abstraction and Encapsulation in C++
  • Function Overriding in C++
  • Virtual Functions and Runtime Polymorphism in C++
  • Difference between Inheritance and Polymorphism
  • Function Overloading in C++
  • Constructor Overloading in C++
  • Functions that cannot be overloaded in C++
  • Function overloading and const keyword
  • Function Overloading and Return Type in C++
  • Function Overloading and float in C++
  • C++ Function Overloading and Default Arguments
  • Can main() be overloaded in C++?
  • Function Overloading vs Function Overriding in C++
  • Advantages and Disadvantages of Function Overloading in C++

C++ Operator Overloading

  • Operator Overloading in C++
  • Types of Operator Overloading in C++
  • Functors in C++
  • What are the Operators that Can be and Cannot be Overloaded in C++?
  • Inheritance in C++
  • C++ Inheritance Access
  • Multiple Inheritance in C++
  • C++ Hierarchical Inheritance
  • C++ Multilevel Inheritance
  • Constructor in Multiple Inheritance in C++
  • Inheritance and Friendship in C++
  • Does overloading work with Inheritance?

C++ Virtual Functions

  • Virtual Function in C++
  • Virtual Functions in Derived Classes in C++
  • Default Arguments and Virtual Function in C++
  • Can Virtual Functions be Inlined in C++?
  • Virtual Destructor
  • Advanced C++ | Virtual Constructor
  • Advanced C++ | Virtual Copy Constructor
  • Pure Virtual Functions and Abstract Classes in C++
  • Pure Virtual Destructor in C++
  • Can Static Functions Be Virtual in C++?
  • RTTI (Run-Time Type Information) in C++
  • Can Virtual Functions be Private in C++?

C++ Exception Handling

  • Exception Handling in C++
  • Exception Handling using classes in C++
  • Stack Unwinding in C++
  • User-defined Custom Exception with class in C++

C++ Files and Streams

  • File Handling through C++ Classes
  • I/O Redirection in C++
  • Templates in C++ with Examples
  • Template Specialization in C++
  • Using Keyword in C++ STL

C++ Standard Template Library (STL)

  • The C++ Standard Template Library (STL)
  • Containers in C++ STL (Standard Template Library)
  • Introduction to Iterators in C++
  • Algorithm Library | C++ Magicians STL Algorithm

C++ Preprocessors

  • C Preprocessors
  • C Preprocessor Directives
  • #include in C
  • Difference between Preprocessor Directives and Function Templates in C++

C++ Namespace

  • Namespace in C++ | Set 1 (Introduction)
  • namespace in C++ | Set 2 (Extending namespace and Unnamed namespace)
  • Namespace in C++ | Set 3 (Accessing, creating header, nesting and aliasing)
  • C++ Inline Namespaces and Usage of the "using" Directive Inside Namespaces

Advanced C++

  • Multithreading in C++
  • Smart Pointers in C++
  • auto_ptr vs unique_ptr vs shared_ptr vs weak_ptr in C++
  • Type of 'this' Pointer in C++
  • "delete this" in C++
  • Passing a Function as a Parameter in C++
  • Signal Handling in C++
  • Generics in C++
  • Difference between C++ and Objective C
  • Write a C program that won't compile in C++
  • Write a program that produces different results in C and C++
  • How does 'void*' differ in C and C++?
  • Type Difference of Character Literals in C and C++
  • Cin-Cout vs Scanf-Printf

C++ vs Java

  • Similarities and Difference between Java and C++
  • Comparison of Inheritance in C++ and Java
  • How Does Default Virtual Behavior Differ in C++ and Java?
  • Comparison of Exception Handling in C++ and Java
  • Foreach in C++ and Java
  • Templates in C++ vs Generics in Java
  • Floating Point Operations & Associativity in C, C++ and Java

Competitive Programming in C++

  • Competitive Programming - A Complete Guide
  • C++ tricks for competitive programming (for C++ 11)
  • Writing C/C++ code efficiently in Competitive programming
  • Why C++ is best for Competitive Programming?
  • Test Case Generation | Set 1 (Random Numbers, Arrays and Matrices)
  • Fast I/O for Competitive Programming
  • Setting up Sublime Text for C++ Competitive Programming Environment
  • How to setup Competitive Programming in Visual Studio Code for C++
  • Which C++ libraries are useful for competitive programming?
  • Common mistakes to be avoided in Competitive Programming in C++ | Beginners
  • C++ Interview Questions and Answers (2024)
  • Top C++ STL Interview Questions and Answers
  • 30 OOPs Interview Questions and Answers (2024)
  • Top C++ Exception Handling Interview Questions and Answers
  • C++ Programming Examples

Constructor in C++ is a special method that is invoked automatically at the time of object creation. It is used to initialize the data members of new objects generally. The constructor in C++ has the same name as the class or structure. It constructs the values i.e. provides data for the object which is why it is known as a constructor.

  • Constructor is a member function of a class, whose name is the same as the class name.
  • Constructor is a special type of member function that is used to initialize the data members for an object of a class automatically when an object of the same class is created.
  • Constructor is invoked at the time of object creation. It constructs the values i.e. provides data for the object that is why it is known as a constructor.
  • Constructors do not return value, hence they do not have a return type.
  • A constructor gets called automatically when we create the object of the class.
  • Constructors can be overloaded.
  • A constructor can not be declared virtual.

Syntax of Constructors in C++

The prototype of the constructor looks like this:

The constructor can be defined inside the class declaration or outside the class declaration

Syntax for Defining the Constructor Within the Class

Syntax for defining the constructor outside the class, examples of constructors in c++.

The below examples demonstrate how to declare constructors for a class in C++:

Example 1: Defining the Constructor Within the Class

 example 2: defining the constructor outside the class.

Note: We can make the constructor defined outside the class as inline to make it equivalent to the in class definition. But note that inline is not an instruction to the compiler, it is only the request which compiler may or may not implement depending on the circumtances.

Characteristics of Constructors in C++

The following are some main characteristics of the constructors in C++:

  • The name of the constructor is the same as its class name.
  • Constructors are mostly declared in the public section of the class though they can be declared in the private section of the class.
  • Constructors do not return values; hence they do not have a return type.
  • A constructor cannot be inherited.
  • The addresses of the Constructor cannot be referred to.
  • The constructor makes implicit calls to new and delete operators during memory allocation.

Types of Constructor in C++

Constructors can be classified based on in which situations they are being used. There are 4 types of constructors in C++:

  • Default Constructor
  • Parameterized Constructor
  • Copy Constructor
  • Move Constructor

types of constructors in c++

Let us understand the types of constructors in C++ by taking a real-world example. Suppose you went to a shop to buy a marker. When you want to buy a marker, what are the options? The first one you go to a shop and say give me a marker. So just saying give me a marker means that you did not set which brand name and which color, you didn’t mention anything just say you want a marker. So when we said just I want a marker whatever the frequently sold marker is there in the market or his shop he will simply hand over that. And this is what a default constructor is!

The second method is you go to a shop and say I want a marker red in color and XYZ brand. So you are mentioning this and he will give you that marker. So in this case you have given the parameters. And this is what a parameterized constructor is!

Then the third one you go to a shop and say I want a marker like this(a physical marker on your hand). So the shopkeeper will see that marker. Okay, and he will give a new marker for you. So copy of that marker. And that’s what a copy constructor is!

Now, assume that you don’t to buy a new marker but instead take ownership of your friend’s marker. It means taking ownership of already present resources instead of getting a new one. That’s what a move constructor is!

1. Default Constructor in C++

A default constructor is a constructor that doesn’t take any argument. It has no parameters. It is also called a zero-argument constructor.

Syntax of Default Constructor

Examples of default constructor.

The below examples demonstrate how to use the default constructors in C++.

Note: Even if we do not define any constructor explicitly, the compiler will automatically provide a default constructor implicitly.

As we can see, we are able the object of class student is created without passing any argument even when we haven’t defined any explicit default constructor for it.

2. Parameterized Constructor in C++

Parameterized Constructors make it possible to pass arguments to constructors. Typically, these arguments help initialize an object when it is created. To create a parameterized constructor, simply add parameters to it the way you would to any other function. When you define the constructor’s body, use the parameters to initialize the object.

Syntax of Parameterized Constructor

Examples of parameterized constructor.

The below examples demonstrate how to use the parameterized constructors in C++.

Example 1: Defining Parameterized Constructor Inside the Class.

Example 2: Defining Parameterized Constructor Outside the Class.

When an object is declared in a parameterized constructor, the initial values have to be passed as arguments to the constructor function. The normal way of object declaration may not work. The parameterized constructors can be called explicitly or implicitly:

When the parameterized constructor is defined and no default constructor is defined explicitly, the compiler will not implicitly create the default constructor and hence create a simple object as:

will flash an error.

Important Note: Whenever we define one or more non-default constructors( with parameters ) for a class, a default constructor( without parameters ) should also be explicitly defined as the compiler will not provide a default constructor in this case. However, it is not necessary but it’s considered to be the best practice to always define a default constructor.

Uses of Parameterized Constructor

  • It is used to initialize the various data elements of different objects with different values when they are created.
  • It is used to overload constructors.

Default Arguments with C++ Parameterized Constructor

Just like normal functions, we can also define default values for the arguments of parameterized constructors. All the rules of the default arguments will be applied to these parameters.

Example 3: Defining Parameterized Constructor with Default Values

As we can see, when the default values are assigned to every argument of the parameterized constructor, it is legal to create the object without passing any parameters just like default constructors. So, this type of constructor works as both a default and parameterized constructor.

3. Copy Constructor in C++

A copy constructor is a member function that initializes an object using another object of the same class.

Syntax of Copy Constructor

Copy constructor takes a reference to an object of the same class as an argument.

Just like the default constructor, the C++ compiler also provides an implicit copy constructor if the explicit copy constructor definition is not present. Here, it is to be noted that, unlike the default constructor where the presence of any type of explicit constructor results in the deletion of the implicit default constructor, the implicit copy constructor will always be created by the compiler if there is no explicit copy constructor or explicit move constructor is present.

Examples of Copy Constructor

The below examples demonstrate how to use the copy constructors in C++.

Example 1: Illustration of Implicit Copy Constructor

Example 2: Defining of Explicit Copy Constructor

Example 3: Defining of Explicit Copy Constructor with Parameterized Constructor

Uses of Copy Constructor

  • Constructs a new object by copying values from an existing object.
  • Can be used to perform deep copy.
  • Modify specific attributes during the copy process if needed.

4. Move Constructor in C++

The move constructor is a recent addition to the family of constructors in C++. It is like a copy constructor that constructs the object from the already existing objects., but instead of copying the object in the new memory, it makes use of move semantics to transfer the ownership of the already created object to the new object without creating extra copies.

It can be seen as stealing the resources from other objects.

Syntax of Move Constructor in C++

The move constructor takes the rvalue reference of the object of the same class and transfers the ownership of this object to the newly created object.

Like a copy constructor, the compiler will create a move constructor for each class that does not have any explicit move constructor.

Examples of Move Constructor

The below examples demonstrate how to use the move constructors in C++.

Example 1: Defining Move Constructor

Uses of Move Constructor

  • Instead of making copies, move constructors efficiently transfer ownership of these resources.
  • This prevents unnecessary memory copying and reduces overhead.
  • You can define your own move constructor to handle specific resource transfers.

A destructor is also a special member function as a constructor. Destructor destroys the class objects created by the constructor. Destructor has the same name as their class name preceded by a tilde (~) symbol. It is not possible to define more than one destructor. The destructor is only one way to destroy the object created by the constructor. Hence destructor can-not be overloaded. Destructor neither requires any argument nor returns any value. It is automatically called when the object goes out of scope.  Destructors release memory space occupied by the objects created by the constructor. In destructor , objects are destroyed in the reverse of object creation.

Syntax of Destructors in C++

Like constructors, destructors can also be defined either inside or outside of the class.

The syntax for defining the destructor within the class

The syntax for defining the destructor outside the class

Examples of Destructors in C++

The below examples demonstrate how to use the destructors in C++.

Example 1: Defining a Simple Destructor

Example 2: Counting the Number of Times Object is Created and Destroyed

Characteristics of Destructors in C++

The following are some main characteristics of destructors in C++:

  • Destructor is invoked automatically by the compiler when its corresponding constructor goes out of scope and releases the memory space that is no longer required by the program.
  • Destructor neither requires any argument nor returns any value therefore it cannot be overloaded.
  • Destructor  cannot be declared as static and const;
  • Destructor should be declared in the public section of the program.
  • Destructor is called in the reverse order of its constructor invocation.

Frequently Asked Questions on C++ Constructors

What are the functions that are generated by the compiler by default, if we do not provide them explicitly.

The functions that are generated by the compiler by default if we do not provide them explicitly are: Default Constructor Copy Constructor Move Constructors Assignment Operator Destructor

Can We Make the Constructors Private?

Yes, in C++, constructors can be made private. This means that no external code can directly create an object of that class.

How Constructors Are Different from a Normal Member Function?

A constructor is different from normal functions in following ways:  Constructor has same name as the class itself Default Constructors don’t have input argument however, Copy and Parameterized Constructors have input arguments Constructors don’t have return type A constructor is automatically called when an object is created. It must be placed in public section of class. If we do not specify a constructor, C++ compiler generates a default constructor for object (expects no parameters and has an empty body).

Can We Have More Than One Constructor in a Class?

Yes, we can have more than one constructor in a class. It is called Constructor Overloading .

Related Articles:

  • Quiz on Constructors in C++
  • Output of C++ programs | Set 26 (Constructors)
  • Output of C++ programs | Set 27(Constructors and Destructors)

Please Login to comment...

Similar reads.

  • cpp-constructor
  • School Programming

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

MC++ BLOG

C++ Core Guidelines: Constructors

The lifecycle of each object starts with its creation; therefore, this post will be about the thirteen most fundamental rules for objects: constructor rules.

Twelve rules are too many for one post. Therefore, I will cover only the first eleven. Why not just ten rules? Because the eleventh rule is just too attractive. The remaining two are part of the next post. Here are the thirteen rules.

stork 1324371 1280

Constructor rules:

C.40: define a constructor if a class has an invariant, c.41: a constructor should create a fully initialized object, c.42: if a constructor cannot construct a valid object, throw an exception, c.43: ensure that a value type class has a default constructor, c.44: prefer default constructors to be simple and non-throwing, c.45: don’t define a default constructor that only initializes data members; use member initializers instead, c.46: by default, declare single-argument constructors explicit, c.47: define and initialize member variables in the order of member declaration, c.48: prefer in-class initializers to member initializers in constructors for constant initializers, c.49: prefer initialization to assignment in constructors, c.50: use a factory function if you need “virtual behavior” during initialization.

  • C.51: Use delegating constructors to represent common actions for all constructors of a class
  • C.52: Use inheriting constructors to import constructors into a derived class that does not need further explicit initialization

So, let’s look at the rules in detail. For further analysis, use the links to the rules.

An invariant of an object is a characteristic of the object that should hold for its entire lifetime. The place to establish such an invariant is the constructor. An invariant can be a valid date.

Modernes C++ Mentoring

Be part of my mentoring programs:

  • " Fundamentals for C++ Professionals " (open)
  • " Design Patterns and Architectural Patterns with C++ " (open)
  • " C++20: Get the Details " (open)
  • " Concurrency with Modern C++ " (starts March 2024)

Do you want to stay informed: Subscribe.

This rule is quite similar to the previous one. Accordingly, creating the fully initialized object is the job of the constructor. A class having an init method is asking for trouble.

The user might mistakenly invoke read before init or might forget to invoke init.

Accordingly to the previous rule: throw an exception if you can not construct a valid object. There is not much to add. If you work with an invalid object, you must check its state before its usage. This is highly error-prone. Here is an example from the guidelines:

A value type is a type that behaves like an int. A value type is similar to a regular type. I wrote about value types and regular types in the post about concrete types . Having a default constructor makes it easier to use your type. Many constructors of STL containers rely on the fact that your type has a default constructor. For example, for the value of an ordered associative container such as std::map . If all the class members have a default constructor, the compiler will implicitly generate one for your class.

Error handling is a lot easier with default constructors that can not throw. The guidelines provide a simple example:

This is one of my favorite features of C++11. Initializing class members directly in the class body makes the writing of constructors a lot easier and sometimes obsolete. Class X1 classically defines its members (before C++11) and X2 in a preferred way. A nice side effect is that the compiler automatically generates the constructor for X2 .

This is a crucial rule. Single-argument constructors are often called conversion constructors. If you make them not explicit, an implicit conversion may happen.

The implicit conversion from int to String is impossible because the constructor is explicit. If instead of the explicit constructor, the out-commented implicit constructor were used, you would get a string of size 10

The class members are initialized in the order of their declaration. If you initialize them in the constructor initializer in a different order, you may get surprised.

In-class initializer makes it a lot easier to define the constructors. Additionally, you can not forget to initialize a member.

While the in-class initialization establishes the default behavior of an object, the constructor (1) allows the variation of the default behavior.

That is quite an old rule. The most obvious pros of initialization to the assignment are that you can not forget to assign a value and use it uninitialized. Initialization may be faster but never slower than assignment.

Calling a virtual function from a constructor will not work as expected. For protection reasons, the virtual call mechanism is disabled in the constructor because the creation of the derived class hasn’t happened.

Hence, the following example will call the Base version of the virtual function f.

 Here is the output of the program.

virtualConstructor

Let’s create a factory function to have virtual behavior during object initialization. To deal with the ownership, the factory function should return a smart pointer such as a std::unique_ptr or a std::shared_ptr. As a starting point, I will use the previous example but make the constructor of Base protected; therefore, only objects of the class Derived can be created.

At the end of the initialization, the virtual function f (1) should be called. (2) is the factory function. This factory function calls f after creating a std::unique_ptr and returns it . If Derived is derived from Base, then std::unique_ptr<Dervived> is implicitly convertible to a std::unique_ptr<Base> . Finally, we get our virtual behavior during initialization.

virtualInitialisation

There is one risk with this technique. If the base goes out of scope, you must ensure that the Derived destructor is called. This is the reason for the virtual destructor of Base (4).  If the destructor is not virtual, you will get undefined behavior. Strange, but if I used a std::shared_ptr instead of a std::unique_ptr for the factory method, the virtual destructor of Base is unnecessary. 

Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

  • C++ – The Core Language
  • C++ – The Standard Library
  • C++ – Compact
  • C++11 and C++14
  • Concurrency with Modern C++
  • Design Pattern and Architectural Pattern with C++
  • Embedded Programming with Modern C++
  • Generic Programming (Templates) with C++
  • Clean Code with Modern C++

Online Seminars (German)

  • Clean Code: Best Practices für modernes C++ (21. Mai 2024 bis 23. Mai 2024)
  • Embedded Programmierung mit modernem C++   (2. Jul 2024 bis 4. Jul 2024)
  • Phone: +49 7472 917441
  • Mobil:: +49 176 5506 5086
  • Mail: [email protected]
  • German Seminar Page: www.ModernesCpp.de
  • Mentoring Page: www.ModernesCpp.org

Modernes C++ Mentoring,

c constructor assignment initialization

You might also like

Lambda

Leave a Reply

Leave a reply cancel reply.

Your email address will not be published. Required fields are marked *

RainerGrimmSmall

Learn C++ practically and Get Certified .

Popular Tutorials

Popular examples, reference materials, learn c++ interactively, introduction to c++.

  • Getting Started With C++
  • Your First C++ Program
  • C++ Comments

C++ Fundamentals

  • C++ Keywords and Identifiers
  • C++ Variables, Literals and Constants
  • C++ Data Types
  • C++ Type Modifiers
  • C++ Constants
  • C++ Basic Input/Output
  • C++ Operators

Flow Control

  • C++ Relational and Logical Operators
  • C++ if, if...else and Nested if...else
  • C++ for Loop
  • C++ while and do...while Loop
  • C++ break Statement
  • C++ continue Statement
  • C++ goto Statement
  • C++ switch..case Statement
  • C++ Ternary Operator
  • C++ Functions
  • C++ Programming Default Arguments
  • C++ Function Overloading
  • C++ Inline Functions
  • C++ Recursion

Arrays and Strings

  • C++ Array to Function
  • C++ Multidimensional Arrays
  • C++ String Class

Pointers and References

  • C++ Pointers
  • C++ Pointers and Arrays
  • C++ References: Using Pointers
  • C++ Call by Reference: Using pointers
  • C++ Memory Management: new and delete

Structures and Enumerations

  • C++ Structures
  • C++ Structure and Function
  • C++ Pointers to Structure
  • C++ Enumeration

Object Oriented Programming

C++ Classes and Objects

C++ Constructors

C++ Constructor Overloading

C++ Destructors

  • C++ Access Modifiers
  • C++ Encapsulation
  • C++ friend Function and friend Classes

Inheritance & Polymorphism

  • C++ Inheritance
  • C++ Public, Protected and Private Inheritance
  • C++ Multiple, Multilevel and Hierarchical Inheritance
  • C++ Function Overriding
  • C++ Virtual Functions
  • C++ Abstract Class and Pure Virtual Function

STL - Vector, Queue & Stack

  • C++ Standard Template Library
  • C++ STL Containers
  • C++ std::array
  • C++ Vectors
  • C++ Forward List
  • C++ Priority Queue

STL - Map & Set

  • C++ Multimap
  • C++ Multiset
  • C++ Unordered Map
  • C++ Unordered Set
  • C++ Unordered Multiset
  • C++ Unordered Multimap

STL - Iterators & Algorithms

  • C++ Iterators
  • C++ Algorithm
  • C++ Functor

Additional Topics

  • C++ Exceptions Handling
  • C++ File Handling
  • C++ Ranged for Loop
  • C++ Nested Loop
  • C++ Function Template

C++ Class Templates

  • C++ Type Conversion
  • C++ Type Conversion Operators
  • C++ Operator Overloading

Advanced Topics

  • C++ Namespaces
  • C++ Preprocessors and Macros
  • C++ Storage Class
  • C++ Bitwise Operators
  • C++ Buffers
  • C++ istream
  • C++ ostream

C++ Tutorials

  • C++ clock()
  • How to pass and return object from C++ Functions?

A constructor is a special member function that is called automatically when an object is created.

In C++, a constructor has the same name as that of the class , and it does not have a return type. For example,

Here, the function Wall() is a constructor of the class Wall . Notice that the constructor

  • has the same name as the class,
  • does not have a return type, and
  • C++ Default Constructor

A constructor with no parameters is known as a default constructor . For example,

Here, when the wall1 object is created, the Wall() constructor is called. length{5.5} is invoked when the constructor is called, and sets the length variable of the object to 5.5 .

Note: If we have not defined any constructor, copy constructor, or move constructor in our class, then the C++ compiler will automatically create a default constructor with no parameters and empty body.

Defaulted Constructor

When we have to rely on default constructor to initialize the member variables of a class, we should explicitly mark the constructor as default in the following way:

If we want to set a default value, then we should use value initialization. That is, we include the default value inside braces in the declaration of member variables in the follwing way.

Let's see an example:

  • C++ Parameterized Constructor

In C++, a constructor with parameters is known as a parameterized constructor. This is the preferred method to initialize member data. For example,

Here, we have defined a parameterized constructor Wall() that has two parameters: double len and double hgt . The values contained in these parameters are used to initialize the member variables length and height .

: length{len}, height{hgt} is the member initializer list.

  • length{len} initializes the member variable length with the value of the parameter len
  • height{hgt} initializes the member variable height with the value of the parameter hgt .

When we create an object of the Wall class, we pass the values for the member variables as arguments. The code for this is:

With the member variables thus initialized, we can now calculate the area of the wall with the calculateArea() method.

Note : A constructor is primarily used to initialize objects. They are also used to run a default code when an object is created.

  • C++ Member Initializer List

Consider the constructor:

is member initializer list.

The member initializer list is used to initialize the member variables of a class.

The order or initialization of the member variables is according to the order of their declaration in the class rather than their declaration in the member initializer list.

Since the member variables are declared in the class in the following order:

The length variable will be initialized first even if we define our constructor as following:

  • C++ Copy Constructor

The copy constructor in C++ is used to copy data from one object to another. For example,

In this program, we have used a copy constructor to copy the contents of one object of the Wall class to another. The code of the copy constructor is:

Notice that the parameter of this constructor has the address of an object of the Wall class.

We then assign the values of the variables of the obj object to the corresponding variables of the object, calling the copy constructor. This is how the contents of the object are copied.

In main() , we then create two objects wall1 and wall2 and then copy the contents of wall1 to wall2 :

Here, the wall2 object calls its copy constructor by passing the reference of the wall1 object as its argument.

  • C++ Default Copy Constructor

If we don't define any copy constructor, move constructor, or move assignment in our class, then the C++ compiler will automatically create a default copy constructor that does memberwise copy assignment. It suffices in most cases. For example,

In this program, we have not defined a copy constructor. The compiler used the default copy constructor to copy the contents of one object of the Wall class to another.

  • C++ Friend Function and Classes

Table of Contents

  • Introduction

Sorry about that.

Related Tutorials

C++ Tutorial

IMAGES

  1. C++ : Assignment initialization of a constructor

    c constructor assignment initialization

  2. C++ : Initialization lists in constructor

    c constructor assignment initialization

  3. C++ tutorial || onlinetraining||Initialization of members in

    c constructor assignment initialization

  4. Initializer List in constructor in C++ #Initializer #Initialization #

    c constructor assignment initialization

  5. C++ : Constructor initialization Vs assignment

    c constructor assignment initialization

  6. Initialize An Array With User Input

    c constructor assignment initialization

VIDEO

  1. MGT501 (Human Resource Management) Assignment No.1 Solution Spring 2024

  2. 3.a

  3. [Object Oriented in Urdu/Hindi] L-9

  4. C++ : Circular dependency in constructor initialization list

  5. C++ Classes Member Initialization List and Default Constructor Parameters

  6. Constructor member Initialization in C++

COMMENTS

  1. Constructors and member initializer lists

    In the definition of a constructor of a class, member initializer list specifies the initializers for direct and virtual bases and non-static data members. (Not to be confused with std::initializer_list .) A constructor cannot be a coroutine . A constructor cannot have an explicit object parameter .

  2. C++: Where to initialize variables in constructor

    139. If you do not mention a variable in a class's initialization list, the constructor will default initialize it before entering the body of the constructor you've written. This means that option 2 will lead to each variable being written to twice, once for the default initialization and once for the assignment in the constructor body.

  3. c++

    To initialize is to make ready for use. And when we're talking about a variable, that means giving the variable a first, useful value. And one way to do that is by using an assignment. So it's pretty subtle: assignment is one way to do initialization. Assignment works well for initializing e.g. an int, but it doesn't work well for initializing ...

  4. 9.6. Constructors And Initializer Lists

    Initializer list vs. assignment: Member initialization. Constructors often initialize member variables with function arguments. Simple assignment statements work, but an initializer list is preferred. In this example, gcd is a function that calculates the greatest common divisor - the largest number that divides both function arguments evenly.

  5. PDF Constructors and Assignment

    Why Constructors? Initialization is defined by the constructor for a type. Assignment is defined by the assignment operator for a type. ... constructors and assignment. If you don't the compiler will create a default version for you. Constructors We will be looking at three kinds of

  6. 14.10

    This lesson continues our introduction of constructors from lesson 14.9 -- Introduction to constructors.. Member initialization via a member initialization list. To have a constructor initialize members, we do so using a member initializer list (often called a "member initialization list"). Do not confuse this with the similarly named "initializer list" that is used to initialize ...

  7. Constructors (C++)

    Initializer list constructors. If a constructor takes a std::initializer_list<T> as its parameter, and any other parameters have default arguments, that constructor is selected in overload resolution when the class is instantiated through direct initialization. You can use the initializer_list to initialize any member that can accept it.

  8. 1.4

    1.4 — Variable assignment and initialization. Alex April 25, 2024. In the previous lesson ( 1.3 -- Introduction to objects and variables ), we covered how to define a variable that we can use to store values. In this lesson, we'll explore how to actually put values into variables and use those values. As a reminder, here's a short snippet ...

  9. 24.4

    By restricting the initialization of variables to the constructor of the class those variables belong to, C++ ensures that all variables are initialized only once. The end result is that the above example does not work because m_id was inherited from Base, and only non-inherited variables can be initialized in the member initializer list.

  10. Constructors, C++ FAQ

    Constructors build objects from dust. Constructors are like "init functions". They turn a pile of arbitrary bits into a living object. Minimally they initialize internally used fields. They may also allocate resources (memory, files, semaphores, sockets, etc). "ctor" is a typical abbreviation for constructor.

  11. Constructors and member initializer lists

    Constructor is a special non-static member function of a class that is used to initialize objects of its class type.. In the definition of a constructor of a class, member initializer list specifies the initializers for direct and virtual base subobjects and non-static data members. ( Not to be confused with std::initializer_list) . Syntax. Constructors are declared using member function ...

  12. Copy Constructor vs Assignment Operator in C++

    C++ compiler implicitly provides a copy constructor, if no copy constructor is defined in the class. A bitwise copy gets created, if the Assignment operator is not overloaded. Consider the following C++ program. Explanation: Here, t2 = t1; calls the assignment operator, same as t2.operator= (t1); and Test t3 = t1; calls the copy constructor ...

  13. Should I use the initializer list or perform assignments in my C++

    An example where when you should (but aren't forced to) use initialization lists is when you have an aggregate object and the following points are valid: The aggregate has a default constructor. You need to setup the object with non-default values. The aggregate has a constructor that allows you to set the desired non-default values.

  14. Initialization vs. Assignment[C++ class-defined objects]

    The first is assignment and the second is initialization, which can occur in three ways: When one object explicitly initializes another, such as in a declaration, When a copy of an object is made to be passed to a function, or. When a temporary object is generated (most commonly, as a return value). The copy constructor applies only to ...

  15. Constructors in C++

    Constructor is a special type of member function that is used to initialize the data members for an object of a class automatically when an object of the same class is created. Constructor is invoked at the time of object creation. It constructs the values i.e. provides data for the object that is why it is known as a constructor.

  16. C++ Core Guidelines: Constructors

    C.49: Prefer initialization to assignment in constructors; C.50: Use a factory function if you need "virtual behavior" during initialization; C.51: Use delegating constructors to represent common actions for all constructors of a class; C.52: Use inheriting constructors to import constructors into a derived class that does not need further ...

  17. c++

    When you initialize fields via Member initializer list the constructors will be called once and the object will be constructed and initialized in one operation. If you use assignment then the fields will be first initialized with default constructors and then reassigned (via assignment operator) with actual values.

  18. C++ Constructors (With Examples)

    C++ Default Constructor. A constructor with no parameters is known as a default constructor.For example, // C++ program to demonstrate the use of default constructor #include <iostream> using namespace std; // declare a class class Wall { private: double length; public: // default constructor to initialize variable Wall() : length{5.5} { cout << "Creating a wall."

  19. c++

    Initializing const members and other special cases (such a parent classes) can be accomplished in the initializer list. class Foo {private: const int data;public: Foo(int x) : data(x) {}}; Or, similarly, for parent initialization.