Why must const members be initialized in the constructor initializer rather than in its body?
In C++, an object is considered fully initialised when execution enters the body of the constructor.
You said:
"i wanted to know why const must be
intialized in constructor initializer
list rather than in it's body ?."
What you are missing is that initialisation happens in the initialisation list, and assignment happens in the body of the constructor. The steps in logic:
1) A const object can only be initialised.
2) An object has all of its members initialised in the initialisation list. Even if you do not explicitly initialise them there, the compiler will happily do so for you :-)
3) Therefore, putting 1) and 2) together, a member which is const can only ever have a value assigned to it at initialisation, which happens during the initialisation list.
The constructor initializer list and const variable
Basically when data members are declared constant they have to have some value before the object is constructed Hence we use member initializer so that before the object is constructed the data member has some value.
in this program till the end the data member will have the same value
for real scenario:
For example you have to make a payroll program in which each employee has a first name and last name so you wouldn't want functions to accidentally modify their names so hence to prevent this you can keep them constant.
Why constant data member of a class need to be initialized at the constructor?
A::A(){
a = 1;
b = 9; // Why we need to initialize this only at the constructor.
}
Is not initialization but it is Assignment.a
and b
are already constructed and you assign them values in this case. The const
qualifier demands that the variable not be changed after its initialization, allowing this assignment would break that contract.
This is Initialization using Member Initialization list.
A::A():a(1),b(9)
{}
You might want to have a look at this answer of mine to know the difference:
What is the difference between Initializing and Assignment inside constructor?
As for another question, regarding only static constant integral data can be initialized inside the class, please read this answer of mine which explains in greater detail:
Why I can't initialize non-const static member or static array in class?
Why can const members be modified in a constructor?
This is not modification (or assignment) but initialization. e.g.
struct Bar {
const int b = 5; // initialization (via default member initializer)
Bar(int c)
:b(c) // initialization (via member initializer list)
{
b = c; // assignment; which is not allowed
}
};
The const
data member can't be modified or assigned but it could (and need to) be initialized via member initializer list or default member initializer.
If both default member initializer and member initializer are provided on the same data member, the default member initializer will be ignored. That's why b->b
is initialized with value 2
.
If a member has a default member initializer and also appears in the member initialization list in a constructor, the default member initializer is ignored.
On the other hand, the default member initializer takes effect only when the data member is not specified in the member initializer list. e.g.
struct Bar {
const int b = 5; // default member initialization
Bar(int c):b(c) {} // b is initialized with c
Bar() {} // b is initialized with 5
};
Why is a constructor necessary in a const member struct?
From §8.5 [dcl.init]/7:
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
The default constructor of AClass
default-initializes the const
member (see below), so that member must have a user-provided default constructor. Using = default
does not result in a user-provided default constructor, as can be seen in §8.4.2 [dcl.fct.def.default]/4:
A function is user-provided if it is user-declared and not explicitly defaulted or
deleted on its first declaration.
The member is default-initialized per §12.6.2 [class.base.init]/8:
In a non-delegating constructor, if a given non-static data member or base class is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer) and the entity is not a virtual base class of an abstract class (10.4), then
— if the entity is a non-static data member that has a brace-or-equal-initializer , the entity is initialized as specified in 8.5;
— otherwise, if the entity is an anonymous union or a variant member (9.5), no initialization is performed;
— otherwise, the entity is default-initialized (8.5).
C++ class const member intialization within constructor body
Collect all the calculation into a static calculation function.
struct Class {
static int calcValue(int value) {
if (Function1(value) {
Function2(&value);
return value;
}
return value * 2;
}
Class(int val)
: value(calcValue(val))
{}
};
Initialize const member variables
If you can afford a C++11 compiler, consider delegating constructors:
class Foo
{
// ...
bool const bar;
bool const baz;
Foo(void const*);
// ...
Foo(my_struct const* s); // Possibly private
};
Foo::Foo(void const* ptr)
: Foo{complex_method(ptr)}
{
}
// ...
Foo::Foo(my_struct const* s)
: bar{calculate_bar(s)}
, baz{calculate_baz(s)}
{
}
As a general advice, be careful declaring your data members as const
, because this makes your class impossible to copy-assign and move-assign. If your class is supposed to be used with value semantics, those operations become desirable. If that's not the case, you can disregard this note.
Initializing C++ const fields after the constructor
You could cast away the constness in the constructor:
class Image {
public:
const int width,height;
Image(const char *filename) : width(0), height(0) {
MetaData md(readDataFromFile(filename));
int* widthModifier = const_cast<int*>(&width);
int* heightModifier = const_cast<int*>(&height);
cout << "Initial width " << width << "\n";
cout << "Initial height " << height << "\n";
*widthModifier = md.GetWidth();
*heightModifier = md.GetHeight();
cout << "After const to the cleaners " << width << "\n";
cout << "After const to the cleaners " << height << "\n";
}
};
That would achieve what you want to do but I must say I personally would stay away from that because it causes undefined behavior according to the standard (excerpt from cppreference)
const_cast makes it possible to form a reference or pointer to
non-const type that is actually referring to a const object ...
Modifying a const object through a non-const
access path ... results in undefined behavior.
I would fear any public data members(at least in regarding your particular example). I would go with Georg's approach or make the data private and provide only the getter.
How to initialize const member variable in a class?
The const
variable specifies whether a variable is modifiable or not. The constant value assigned will be used each time the variable is referenced. The value assigned cannot be modified during program execution.
Bjarne Stroustrup's explanation sums it up briefly:
A class is typically declared in a header file and a header file is typically included into many translation units. However, to avoid complicated linker rules, C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects.
A const
variable has to be declared within the class, but it cannot be defined in it. We need to define the const variable outside the class.
T1() : t( 100 ){}
Here the assignment t = 100
happens in initializer list, much before the class initilization occurs.
Initializing fields in constructor - initializer list vs constructor body
They are not the same if member1
and member2
are non-POD (i.e. non-Plain Old Data) types:
public : Thing(int _foo, int _bar){
member1 = _foo;
member2 = _bar;
}
is equivalent to
public : Thing(int _foo, int _bar) : member1(), member2(){
member1 = _foo;
member2 = _bar;
}
because they will be initialized before the constructor body starts executing, so basically twice the work is done. That also means, if the type of these members don't have default constructor, then your code will not compile.
Related Topics
Using C Function from Other Package in Rcpp
What Exactly Are C++ Definitions, Declarations and Assignments
Finding Nearest Point in an Efficient Way
Training Custom Svm to Use with Hogdescriptor in Opencv
How Can Std::Unique_Ptr Have No Size Overhead
What Exactly Is or Was the Purpose of C++ Function-Style Casts
Same Random Numbers Every Time I Run the Program
How to Ensure That the Template Parameter Is a Subtype of a Desired Type
Uses for Negative Zero Floating Point Value
How to Use Setenv() to Export a Variable in C++
Thread Safety of Std::Map for Read-Only Operations
The C 'Clock()' Function Just Returns a Zero
Should I Inherit from Std::Exception
Difference Between C++11 Std::Bind and Boost::Bind
How to Estimate the Thread Context Switching Overhead
How to Find an Official Reference Listing the Operation of Sse Intrinsic Functions
2D Diamond (Isometric) Map Editor - Textures Extended Infinitely