The constructor initializer list and const variable - c++

probably this might be a very basic question, but still wanna understand some basic concepts...
why do we define a variable as a const ? - to keep the value of that specific variable constant through out the program.
but, when i come across initialization list for constructors, that allows to assign value to the const variable during object construction( i tried the below program for ex.), i'm confused with the basic concept of const keyword itself. can someone clarify this?
what is the purpose of const variable in the following program, if it is allowed to change during object construction? do we have any real time scenarios for these kinda behavior? if so, can you please give some scenarios?
#include<iostream>
using namespace std;
class Test {
const int t;
public:
Test(int t):t(t) {} //Initializer list must be used
int getT() { return t; }
};
int main() {
Test t1(10);
cout<<t1.getT();
return 0;
}

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 do we define a variable as a const ?
A variable is declared const to indicate that it will not be changed.
but, when i come across initialization list for constructors, that allows to assign value to the const variable during object construction( i tried the below program for ex.), i'm confused with the basic concept of const keyword itself. can someone clarify this?
Is it not assignment but construction if it would be of not simple type but of MyClass, there constructor of MyClass would be used, not operator=

It does not change during the object-construction, because it has no (defined) value.
When you supply a const-member in a class, then this is a part of the object's identity and this particular value will stay the same through the object's life.
When declaring a member const you promise the compiler that you won't attempt to change the value of this member.
From MSDN
The const keyword specifies that a variable's value is constant and tells the compiler to prevent the programmer from modifying it.
// constant_values1.cpp
int main() {
const int i = 5;
i = 10; // C3892
i++; // C2105
}

Related

Is modify const in constructor C++ standard?

Is modify const in constructor C++ standard? I was modifying my struct removing fixed-values(default member initializer) to set it later, at constructor-time but I forget to remove const keyword and noticied it later. To my surprise I didn't get a compile-error, it just worked fine but for test case 2 it give a compiler. How are they different?
test case 1:
struct A
{
const int x = 2;
A()
: x(3)
{
}
};
test case 2:
struct A
{
const int x = 2;
A()
{
x = 3; // compile error! error: read-only variable is not assignable
}
};
In the first example you are initializing the constant variable, in the second you are assigning a value to it, after the variable is default constructed. These are different operations and assignment is not possible for constants after their initialization.
This syntax was added in C++11:
struct A
{
const int x = 2;
In this case the 2 is like a "default" value to be used for initialization of x. If you initialize x in your constructor's initialization list, then that is the value used. However if you did not do so, then 2 is used.
This was added to C++11 to avoid the tedium of having to repeat things in the initialization lists if you had multiple constructors.
The thing is that the object must be fully initialized before the body of your constructor can proceed to start playing with it. This means that there must be reserved enough space in memory to which the instance of new object will be placed.
If you declare data member (int x) to be const, you prohibit yourself from ever changing it's value, once it is created, this means that the value must be set during it's creation.
In example 1 you first create the int x and set it to value 3 (which will reside in memory reserved for your object) and only after that the body of your constructor executes.
In example 2 you create new object (with some value for your int x) and than you try to modify it in your constructor, which is prohibited by the const keyword.

Can const member variable of class be initialized in a method instead of constructor?

I have a class and want to create a const int variable but the value for the variable is not available to me in constructor of the class.
In initialization method of the class i get the value. Can I assign it in that method?
As I am assigning it only once (as const says) why it isn't working?
Code is as Following [Just a ProtoType] :
File : A.h
Class A
{
private :
const long int iConstValue;
public :
A();
initClassA();
}
File : A.cpp
A::A()
{
//CanNot initialize iConstValue (Don't have it)
}
A::initClassA(some params)
{
// calculation according to params for iConstValue
iConstValue = (some value)
}
This is not working. Somebody has any Solutions?
NOTE : I Can not get value for iconstValue in constructor by any way as there are some restriction. So Please don't suggest to do that.
A small example:
class A
{
public:
A():a(initial_value_of_a()) {}
private:
const int a;
int initial_value_of_a() { return 5; /* some computation here */ };
};
const doesn't mean you can only assign it once, you can never assign to a const object. A const variable is initialized once and its value cannot change. So you initialize it in the constructor, when all members and bases are initialized, then you can't change it after that.
If you can't get the value on construction you could either make the variable non-const, so you modify it, or maybe you could delay construction until you have all the data, using a placeholder until you construct the real object.
Two-stage construction is a code smell, it's certainly incompatible with const members.
You cannot do that, because you cannot change the value of a const variable. by the time initClassA runs the const data member has already been initialized (to some garbage value in this case). So you can only really initialize the data member to some value in the constructor initializer list.
If you want to set the variable only once, then you can make is non-const, and add a guard so it can only be set once. This isn't pretty but it would work:
class A
{
private :
long int iValue;
bool isInitialised;
public :
A() : iValue(0), isInitialized(false);
bool initClassA() {
if (isInitialized) return false;
iValue = something:
isInitialized = true;
return true;
}
}
But it isn't good practice to have objects that can be initialized or not. Objects should be in a coherent state when constructed, and clients should not have to check whether these objects are initialized.
Maybe what you can do, is change for a int pointer, receive this pointer in your constructor, and change the pointer where you want :P
But it will not be the same functionnality cause it will be the pointer which is const and not anymore the value :/
I think I need to change the design and I should calculate the (or get) the const variables value at constructor any how. As there is no way I can set it's value later.

Why constant data member of a class need to be initialized at the constructor?

I want to know why constant data member of a class need to be initialized at the constructor and why not somewhere else? What is the impact of doing so and not doing so?
I also see that only static constant integral data can be initialized inside the class other than that non of the data members can be initialized inside the class.
for eg:- Suppose below is my class declaration
class A{
int a; // This we can initialize at the constructor or we can set this member by calling "vSet" member function
const int b;
static const int c = 10; //This works fine
public:
A();
~A();
void vSet(int a);
int iAdd();
void vDisplay();
};
And the constructor is defined as mentioned below:-
Edited Section: As previous constructor definition example was wrong
A::A():a(1),b(9){}
Please correct me if I am wrong.
Thanks in advance.
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?
What you're doing is not initialization. It is assignment, so b=9 will NOT even compile, because b is a const, so cannot be assigned any value to it. It should be initialized, and to do that, use member-initialization list as:
A::A() : a(1), b(9)
{ // ^^^^^^^^^^^^ this is called member-initialization list
}
In C++11, you can use in-place initialization as:
class A{
int a = 1; //C++11 only
const int b = 9; //C++11 only
static const int c = 10; //This works fine (both in C++03 and C++11)
//...
};
Because it is constant, it's value cannot be changed. Initializing anywhere else other than the constructor would mean a default initialization, followed by an assignment, which is not permitted for a constant. It would be the equivalent of doing this:
const int i; // OK
i = 42; // Error!
Note that in C++11 it is perfectly OK to do this:
struct Foo {
const int i=42;
const double x = 3.1416;
};
But this follows the same rules, i.e there is no assignment.
A const data is a data that can never be changed. It is initialized once, and then keeps the same value forever.
Because of that, you can't just assign a value to it anywhere.
The constructor, however, is where initialization goes. So here, there is an exception, and you are able to assign a value to your const data. You can do this the classical way, or as many said, as initialization list.
Now, why you can't do this in the class definition (unlike, say, Java) when the variable is not static is another problem, that I know no answer to.
When the body of your constructor is entered, all members and sub-objects are already initialized. The only thing the constructor body can do is to change them – and that is, obviously, not allowed for const members.
You can, however, use an initializer list.
You can't initialize const members outside of a constructor because, well, they're const. By definition, you can't modify them after they've been initialized, and after the object has been constructed, anything that tries to set the value is a modification.
const values are meant to be rvalues, so they cannot appear on the right part of an expression due its constness.
so, when you use this expression on the constructor's body
A::A()
{
a = 1;
b = 9; // Why we need to initialize this only at the constructor.
}
You're using the const value as a lvalue, just as Als mentioned before. The fact is that you're trying to assing a new value to a variable that isn't allowed to change it's value afther it's lifetime had begun.
The correct way to assign values to a constant data member is in the ctor initializer list, that is, BEFORE the lifetime of the member value begins (as mentioned by Nawaz):
A::A() :
a(1),
b(9)
{
}
Finally, on the C++11 standard you're allowed to initialize all data members where it was declared, just like the static const ones.

Which are the implications of return a value as constant, reference and constant reference in C++?

I'm learning C++ and I'm still confused about this. What are the implications of return a value as constant, reference and constant reference in C++ ? For example:
const int exampleOne();
int& exampleTwo();
const int& exampleThree();
Here's the lowdown on all your cases:
• Return by reference: The function call can be used as the left hand side of an assignment. e.g. using operator overloading, if you have operator[] overloaded, you can say something like
a[i] = 7;
(when returning by reference you need to ensure that the object you return is available after the return: you should not return a reference to a local or a temporary)
• Return as constant value: Prevents the function from being used on the left side of an assignment expression. Consider the overloaded operator+. One could write something like:
a + b = c; // This isn't right
Having the return type of operator+ as "const SomeType" allows the return by value and at the same time prevents the expression from being used on the left side of an assignment.
Return as constant value also allows one to prevent typos like these:
if (someFunction() = 2)
when you meant
if (someFunction() == 2)
If someFunction() is declared as
const int someFunction()
then the if() typo above would be caught by the compiler.
• Return as constant reference: This function call cannot appear on the left hand side of an assignment, and you want to avoid making a copy (returning by value). E.g. let's say we have a class Student and we'd like to provide an accessor id() to get the ID of the student:
class Student
{
std::string id_;
public:
const std::string& id() const;
};
const std::string& Student::id()
{
return id_;
}
Consider the id() accessor. This should be declared const to guarantee that the id() member function will not modify the state of the object. Now, consider the return type. If the return type were string& then one could write something like:
Student s;
s.id() = "newId";
which isn't what we want.
We could have returned by value, but in this case returning by reference is more efficient. Making the return type a const string& additionally prevents the id from being modified.
The basic thing to understand is that returning by value will create a new copy of your object. Returning by reference will return a reference to an existing object. NOTE: Just like pointers, you CAN have dangling references. So, don't create an object in a function and return a reference to the object -- it will be destroyed when the function returns, and it will return a dangling reference.
Return by value:
When you have POD (Plain Old Data)
When you want to return a copy of an object
Return by reference:
When you have a performance reason to avoid a copy of the object you are returning, and you understand the lifetime of the object
When you must return a particular instance of an object, and you understand the lifetime of the object
Const / Constant references help you enforce the contracts of your code, and help your users' compilers find usage errors. They do not affect performance.
Returning a constant value isn't a very common idiom, since you're returning a new thing anyway that only the caller can have, so it's not common to have a case where they can't modify it. In your example, you don't know what they're going to do with it, so why should you stop them from modifying it?
Note that in C++ if you don't say that something is a reference or pointer, it's a value so you'll create a new copy of it rather than modifying the original object. This might not be totally obvious if you're coming from other languages that use references by default.
Returning a reference or const reference means that it's actually another object elsewhere, so any modifications to it will affect that other object. A common idiom there might be exposing a private member of a class.
const means that whatever it is can't be modified, so if you return a const reference you can't call any non-const methods on it or modify any data members.
Return by reference.
You can return a reference to some value, such as a class member. That way, you don't create copies. However, you shouldn't return references to values in a stack, as that results in undefined behaviour.
#include <iostream>
using namespace std;
class A{
private: int a;
public:
A(int num):a(num){}
//a to the power of 4.
int& operate(){
this->a*=this->a;
this->a*=this->a;
return this->a;
}
//return constant copy of a.
const int constA(){return this->a;}
//return copy of a.
int getA(){return this->a;}
};
int main(){
A obj(3);
cout <<"a "<<obj.getA()<<endl;
int& b=obj.operate(); //obj.operate() returns a reference!
cout<<"a^4 "<<obj.getA()<<endl;
b++;
cout<<"modified by b: "<<obj.getA()<<endl;
return 0;
}
b and obj.a "point" to the same value, so modifying b modifies the value of obj.a.
$./a.out
a 3
a^4 81
modified by b: 82
Return a const value.
On the other hand, returning a const value indicates that said value cannot be modified. It should be remarked that the returned value is a copy.:
For example,
constA()++;
would result in a compilation error, since the copy returned by constA() is constant. But this is just a copy, it doesn't imply that A::a is constant.
Return a const reference.
This is similiar to returning a const value, except that no copy is return, but a reference to the actual member. However, it cant be modified.
const int& refA(){return this->a;}
const int& b = obj.refA();
b++;
will result in a compilation error.
const int exampleOne();
Returns a const copy of some int. That is, you create a new int which may not be modified. This isn't really useful in most cases because you're creating a copy anyway, so you typically don't care if it gets modified. So why not just return a regular int?
It may make a difference for more complex types, where modifying them may have undesirable sideeffects though. (Conceptually, let's say a function returns an object representing a file handle. If that handle is const, the file is read-only, otherwise it can be modified. Then in some cases it makes sense for a function to return a const value. But in general, returning a const value is uncommon.
int& exampleTwo();
This one returns a reference to an int. This does not affect the lifetime of that value though, so this can lead to undefined behavior in a case such as this:
int& exampleTwo() {
int x = 42;
return x;
}
we're returning a reference to a value that no longer exists. The compiler may warn you about this, but it'll probably compile anyway. But it's meaningless and will cause funky crashes sooner or later. This is used often in other cases though. If the function had been a class member, it could return a reference to a member variable, whose lifetime would last until the object goes out of scope, which means function return value is still valid when the function returns.
const int& exampleThree();
Is mostly the same as above, returning a reference to some value without taking ownership of it or affecting its lifetime. The main difference is that now you're returning a reference to a const (immutable) object. Unlike the first case, this is more often useful, since we're no longer dealing with a copy that no one else knows about, and so modifications may be visible to other parts of the code. (you may have an object that's non-const where it's defined, and a function that allows other parts of the code to get access to it as const, by returning a const reference to it.
Your first case:
const int exampleOne();
With simple types like int, this is almost never what you want, because the const is pointless. Return by value implies a copy, and you can assign to a non-const object freely:
int a = exampleOne(); // perfectly valid.
When I see this, it's usually because whoever wrote the code was trying to be const-correct, which is laudable, but didn't quite understand the implications of what they were writing. However, there are cases with overloaded operators and custom types where it can make a difference.
Some compilers (newer GCCs, Metrowerks, etc) warn on behavior like this with simple types, so it should be avoided.
I think that your question is actually two questions:
What are the implications of returning a const.
What are the implications of returning a reference.
To give you a better answer, I will explain a little more about both concepts.
Regarding the const keyword
The const keyword means that the object cannot be modified through that variable, for instance:
MyObject *o1 = new MyObject;
const MyObject *o2 = o1;
o1->set(...); // Will work and will change the instance variables.
o2->set(...); // Won't compile.
Now, the const keyword can be used in three different contexts:
Assuring the caller of a method that you won't modify the object
For example:
void func(const MyObject &o);
void func(const MyObject *o);
In both cases, any modification made to the object will remain outside the function scope, that's why using the keyword const I assure the caller that I won't be modifying it's instance variables.
Assuring the compiler that a specific method do not mutate the object
If you have a class and some methods that "gets" or "obtains" information from the instance variables without modifying them, then I should be able to use them even if the const keyword is used. For example:
class MyObject
{
...
public:
void setValue(int);
int getValue() const; // The const at the end is the key
};
void funct(const MyObject &o)
{
int val = o.getValue(); // Will compile.
a.setValue(val); // Won't compile.
}
Finally, (your case) returning a const value
This means that the returned object cannot be modified or mutated directly. For example:
const MyObject func();
void func2()
{
int val = func()->getValue(); // Will compile.
func()->setValue(val); // Won't compile.
MyObject o1 = func(); // Won't compile.
MyObject o2 = const_cast<MyObject>(func()); // Will compile.
}
More information about the const keyword: C++ Faq Lite - Const Correctness
Regarding references
Returning or receiving a reference means that the object will not be duplicated. This means that any change made to the value itself will be reflected outside the function scope. For example:
void swap(int &x, int &y)
{
int z = x;
x = y;
y = z;
}
int a = 2; b = 3;
swap(a, b); // a IS THE SAME AS x inside the swap function
So, returning a reference value means that the value can be changed, for instance:
class Foo
{
public:
...
int &val() { return m_val; }
private:
int m_val;
};
Foo f;
f.val() = 4; // Will change m_val.
More information about references: C++ Faq Lite - Reference and value semantics
Now, answering your questions
const int exampleOne();
Means the object returned cannot change through the variable. It's more useful when returning objects.
int& exampleTwo();
Means the object returned is the same as the one inside the function and any change made to that object will be reflected inside the function.
const int& exampleThree();
Means the object returned is the same as the one inside the function and cannot be modified through that variable.
Never thought, that we can return a const value by reference and I don't see the value in doing so..
But, it makes sense if you try to pass a value to a function like this
void func(const int& a);
This has the advantage of telling the compiler to not make a copy of the variable a in memory (which is done when you pass an argument by value and not by reference). The const is here in order to avoid the variable a to be modified.

What are the semantics of a const member function?

I understand that the function is not allowed to change the state of the object, but I thought I read somewhere that the compiler was allowed to assume that if the function was called with the same arguments, it would return the same value and thus could reuse a cached value if it was available. e.g.
class object
{
int get_value(int n) const
{
...
}
...
object x;
int a = x.get_value(1);
...
int b = x.get_value(1);
then the compiler could optimize the second call away and either use the value in a register or simply do b = a;
Is this true?
const is about program semantics and not about implementation details. You should mark a member function const when it does not change the visible state of the object, and should be callable on an object that is itself const. Within a const member function on a class X, the type of this is X const *: pointer to constant X object. Thus all member variables are effectively const within that member function (except mutable ones). If you have a const object, you can only call const member functions on it.
You can use mutable to indicate that a member variable may change even within a const member function. This is typically used to identify variables used for caching results, or for variables that don't affect the actual observable state such as mutexes (you still need to lock the mutex in the const member functions) or use counters.
class X
{
int data;
mutable boost::mutex m;
public:
void set_data(int i)
{
boost::lock_guard<boost::mutex> lk(m);
data=i;
}
int get_data() const // we want to be able to get the data on a const object
{
boost::lock_guard<boost::mutex> lk(m); // this requires m to be non-const
return data;
}
};
If you hold the data by pointer rather than directly (including smart pointers such as std::auto_ptr or boost::shared_ptr) then the pointer becomes const in a const member function, but not the pointed-to data, so you can modify the pointed-to data.
As for caching: in general the compiler cannot do this because the state might change between calls (especially in my multi-threaded example with the mutex). However, if the definition is inline then the compiler can pull the code into the calling function and optimize what it can see there. This might result in the function effectively only being called once.
The next version of the C++ Standard (C++0x) will have a new keyword constexpr. Functions tagged constexpr return a constant value, so the results can be cached. There are limits on what you can do in such a function (in order that the compiler can verify this fact).
The keyword mutable on member variables allows for const functions to alter the state of the object at hand.
And no, it doesn't cache data (at least not all calls) since the following code is a valid const function that changes over time:
int something() const { return m_pSomeObject->NextValue(); }
Note that the pointer can be const, though the object pointed to is not const, therefore the call to NextValue on SomeObject may or may not alter it's own internal state. This causes the function something to return different values each time it's called.
However, I can't answer how the compiler works with const methods. I have heard that it can optimize certain things, though I'd have to look it up to be certain.
No.
A const method is a method that doesn't change the state of the object (i.e. its fields), but you can't assume that given the same input, return value of a const method is determined. In other words, const keyword does NOT imply that the function is one-to-one. For instance a method that returns the current time is a const method but its return value changes between calls.
The const keyword on a member function marks the this parameter as constant. The function can still mute global data (so can't be cached), but not object data (allowing for calls on const objects).
In this context, a const member function means that this is treated as a const pointer also. In practical terms, it means you aren't allowed to modify the state of this inside a const member function.
For no-side-effect functions (i.e., what you're trying to achieve), GCC has a "function attribute" called pure (you use it by saying __attribute__((pure))): http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
I doubt it, the function could still call a global function that altered the state of the world and not violate const.
On top of the fact that the member function can modify global data, it is possible for the member function to modify explicitly declared mutable members of the object in question.
Corey is correct, but bear in mind that any member variables that are marked as mutable can be modified in const member functions.
It also means that these functions can be called from other const functions, or via other const references.
Edit: Damn, was beaten by 9 seconds.... 9!!! :)
const methods are also allowed to modify static locals. For example, the following is perfectly legal (and repeated calls to bar() will return increasing values - not a cached 0):
class Foo
{
public:
int bar() const
{
static int x = 0;
return x++;
}
};