Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Initializer Lists in C++: Setting Up Objects Efficiently, Summaries of C programming

The concept of initializer lists in C++ and their usage in initializing object's instance variables before the constructor runs. It covers the process of object creation in C++, the need for initializer lists, and situations where they are mandatory. The document also discusses the syntax and benefits of using initializer lists.

What you will learn

  • What are the situations where initializer lists are mandatory in C++?
  • When should you use an initializer list instead of the default constructor?
  • What is an initializer list in C++?

Typology: Summaries

2021/2022

Uploaded on 09/12/2022

agrima
agrima 🇺🇸

4.8

(10)

257 documents

1 / 6

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
CS106L
Winter 2007-2008
Handout #15
Feburary 20, 2008
Initializer Lists
_________________________________________________________________________________________________________
Introduction
Normally, when you create a class, you'll initialize all of its instance variables inside the constructor.
However, in some cases you'll need to initialize instance variables before the constructor begins running.
Perhaps you'll have a const instance variable that you cannot assign a value, or maybe you have a class
as an instance variable where you do not want to use the default constructor. For situations like these,
C++ has a construct called the initializer list that you can use to fine-tune the way your data members are
set up. This handout discusses initializer list syntax, situations where initializer lists are appropriate, and
some of the subtleties of initializer lists.
How C++ Constructs Objects
To fully understand why initializer lists exist in the first place, you'll need to understand the way that C++
creates and initializes new objects.
Let's suppose you have the following class:
class SimpleClass
{
public:
SimpleClass();
private:
int myInt;
string myString;
vector<int> myVector;
};
Let's define the SimpleClass constructor as follows:
SimpleClass::SimpleClass()
{
myInt = 5;
myString = "C++!";
myVector.resize(10);
}
What happens when you create a new instance of the class MyClass? It turns out that the simple line of
code MyClass mc actually causes a cascade of events that goes on behind the scenes. Let's take a look at
what happens, step-by-step.
The first thing that C++ does to create an object is to simply allocate enough space for the object. This
means that initially all of your object's variables are holding garbage values. In memory, this looks
something like this:
pf3
pf4
pf5

Partial preview of the text

Download Initializer Lists in C++: Setting Up Objects Efficiently and more Summaries C programming in PDF only on Docsity!

CS106L

Winter 2007- Handout # Feburary 20, 2008

Initializer Lists

_________________________________________________________________________________________________________ Introduction Normally, when you create a class, you'll initialize all of its instance variables inside the constructor. However, in some cases you'll need to initialize instance variables before the constructor begins running. Perhaps you'll have a const instance variable that you cannot assign a value, or maybe you have a class as an instance variable where you do not want to use the default constructor. For situations like these, C++ has a construct called the initializer list that you can use to fine-tune the way your data members are set up. This handout discusses initializer list syntax, situations where initializer lists are appropriate, and some of the subtleties of initializer lists. How C++ Constructs Objects To fully understand why initializer lists exist in the first place, you'll need to understand the way that C++ creates and initializes new objects. Let's suppose you have the following class: class SimpleClass { public: SimpleClass(); private: int myInt; string myString; vector myVector; }; Let's define the SimpleClass constructor as follows: SimpleClass::SimpleClass() { myInt = 5; myString = "C++!"; myVector.resize(10); } What happens when you create a new instance of the class MyClass? It turns out that the simple line of code MyClass mc actually causes a cascade of events that goes on behind the scenes. Let's take a look at what happens, step-by-step. The first thing that C++ does to create an object is to simply allocate enough space for the object. This means that initially all of your object's variables are holding garbage values. In memory, this looks something like this:

New Instance of SimpleClass

  • Space allocated for all objects int myInt ??????? (garbage) string myString (object) Text: ??????? (garbage) Length: ??????? (garbage) vector myVector (object) Values: ??????? (garbage) Length: ??????? (garbage) As you can see, none of the instance variables have been initialized, so they all contain junk. At this point, C++ calls the default constructor of each instance variable. For primitive types, this leaves the variables unchanged. After this step, our object looks something like this: New Instance of SimpleClass
  • Constructors called on all instance variables int myInt ??????? (garbage) string myString (object) Text: "" Length: 0 vector myVector (object) Values: { } Length: 0 Finally, C++ will invoke the object's constructor so you can perform any additional initialization code. Using the constructor defined above, the final version of the new object will look like this:

Space allocated for all objects int myInt ??????? (garbage) string myString (object) Text: ??????? (garbage) Length: ??????? (garbage) vector myVector (object) Values: ??????? (garbage) Length: ??????? (garbage) Constructors called on all instance variables int myInt 5 string myString (object) Text: "C++!" Length: 4 vector myVector (object) Values: {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } Length: 10 SimpleClass constructor invoked. int myInt 5 string myString (object) Text: "C++!" Length: 4 vector myVector (object) Values: {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} Length: 10

As you can see, the values of the instance variables myInt, myString, and myVector are correctly set up before the SimpleClass constructor is called. This is considerably more efficient than the previous version and will run much faster. Note that while in this example we used initializer lists to initialize all of the object's instance variables, there is no requirement that you do so. However, in practice it's usually a good idea to set up all variables in an initializer list to make clear what values you want for each of your data members. When Initializer Lists are Mandatory As seen in this previous example, initializer lists can be quite useful in terms of efficiency. However, there are times where initializer lists are the only syntactically legal way to set up your instance variables. Suppose we'd like to make an object called Counter that supports two functions, increment and decrement, that adjust an internal counter. However, we'd like to add the restriction that the Counter can't drop below 0 or exceed a user-defined limit. Thus we'll use a parametrized constructor that accepts an int representing the maximum value for the Counter and stores it as an instance variable. Since the value of the upper limit will never change, we'll mark it const so that we can't accidentally modify it in our code. The class definition for Counter thus looks something like this: class Counter { public: Counter(int maxValue); void increment(); void decrement(); int getValue() const; private: int value; const int maximum; }; Then we'd like the constructor to look like this: Counter::Counter(int maxValue) { value = 0; maximum = maxValue; // ERROR! } Unfortunately, the above code isn't valid because in the second line we're assigning a value to a variable marked const. Even though we're in the constructor, we still cannot violate the sanctity of constness. To fix this, we'll initialize the value of maximum in the initializer list, so that maximum will be initialized to the value of maxValue, rather than assigned the value maxValue. This is a subtle distinction, so make sure to think about it before proceeding. The correct version of the constructor is thus Counter::Counter(int maxValue) : value(0), maximum(maxValue) { // Empty constructor }