Summary of const keyword
A const variable (local or global) cannot be modified, and must be initialized during declaration. By convention, these const variable are named in uppercase.
Syntax
const int SIZE = 5;
int main() {
const int ROWS = 8;
......
}
void fun (MyClass obj); // pass-by-value (default)
// Invoke copy constructor to make a clone copy
// No side-effect
void fun (MyClass & obj); // pass-by-reference, have side-effect
void fun (const MyClass & obj) // pass-by-reference-to-const
// No side-effect. Cannot modify caller's copy
You can also use const for array to prevent it from being modified inside the function (as array is an pointer).
It is recommended to leave out the const for fundamental types (int, double), as they are passed by value. Although you can use const keyword to prevent modification of these local parameters (which is rarely necessary), the keyword can be confusing. If needed, you may include it in the implementation, but leave them out from the header.
const function parameters = not modifying the caller's copy (in pass-by-reference).
For example, if we overload the + operator for the MyComplex class:
MyComplex operator+ (const MyComplex & lhs, const MyComplex & rhs);
// non-const return type can be used as lvalue
MyComplex c1, c2, c3;
c1 + c2 = c3; // Valid if the return type is non-const
// Not meaningful and possibly a misspelling of
// c1 + c2 == c3
Function return value of fundamental types can never be the lvalue, and trigger compilation error.
If a function is overloaded with a const and a non-const version, a const object will match with a const member function. A non-const object will match with a non-const function. For example, the at()function of string class has two versions:
char & at (size_t pos); // non-const member function
const char & at (size_t pos) const; // const member function
A const string object will invoke the const version, which returns a const char & that cannot be used a lvalue.
const string str1("hello"); // const string object
cout << str1.at(1); // okay
str1.at(1) = 'x'; // error - returned const char & cannot be lvalue
string str2("again"); // non-const string object
str2.at(1) = 'x'; // okay
int i1 = 8, i2 = 9;
const int * iptr = &i1; // non-constant pointer pointing to constant data
// *iptr = 9; // error: assignment of read-only location
iptr = &i2; // okay
Constant pointer to non-constant data: Data pointed to CAN be changed; but pointer CANNOT be changed to point to another data. For example,
int i1 = 8, i2 = 9;
int * const iptr = &i1; // constant pointer pointing to non-constant data
*iptr = 9; // okay
// iptr = &i2; // error: assignment of read-only variable
Constant pointer to constant data: Data pointed to CANNOT be changed; and pointer CANNOT be changed to point to another data. For example,
int i1 = 8, i2 = 9;
const int * const iptr = &i1; // constant pointer pointing to constant data
// *iptr = 9; // error: assignment of read-only variable
// iptr = &i2; // error: assignment of read-only variable
Non-constant pointer to non-constant data: Data pointed to CAN be changed; and pointer CAN be changed to point to another data. For example,
*, the pointer itself is a constant.
Syntax
const int SIZE = 5;
int main() {
const int ROWS = 8;
......
}
Function's Parameters
In C++, objects are pass-by-value into function by default, which has no side effect but involves calling the copy constructor to make a clone copy (an expensive operation for huge objects). Objects should be passed into function by reference as far as possible for performance. However, in pass-by-reference, changes made inside the function have side effect of modifying the caller's object. We could use keyword const to enforce immutability, if we do not wish to change the object inside the function. Instead of using pass-by-value to prevent side-effect, it is better to use pass-by-reference-to-const.void fun (MyClass obj); // pass-by-value (default)
// Invoke copy constructor to make a clone copy
// No side-effect
void fun (MyClass & obj); // pass-by-reference, have side-effect
void fun (const MyClass & obj) // pass-by-reference-to-const
// No side-effect. Cannot modify caller's copy
You can also use const for array to prevent it from being modified inside the function (as array is an pointer).
It is recommended to leave out the const for fundamental types (int, double), as they are passed by value. Although you can use const keyword to prevent modification of these local parameters (which is rarely necessary), the keyword can be confusing. If needed, you may include it in the implementation, but leave them out from the header.
const function parameters = not modifying the caller's copy (in pass-by-reference).
Function's Return Value
For object return type, we can use const to prevent it to be used as the lvalue, e.g., f() = x. A const return object cannot be a lvalue (e.g., for assignment); while a non-const return object can.For example, if we overload the + operator for the MyComplex class:
MyComplex operator+ (const MyComplex & lhs, const MyComplex & rhs);
// non-const return type can be used as lvalue
MyComplex c1, c2, c3;
c1 + c2 = c3; // Valid if the return type is non-const
// Not meaningful and possibly a misspelling of
// c1 + c2 == c3
Function return value of fundamental types can never be the lvalue, and trigger compilation error.
Class
- A const data member cannot be modified (as usual).
- A const member function (with const keyword at the end of the function) cannot modify data members.
Object
A const object can only invoke const member function. It cannot invoke non-const member function. A non-const object can invoke both const and non-const member function.If a function is overloaded with a const and a non-const version, a const object will match with a const member function. A non-const object will match with a non-const function. For example, the at()function of string class has two versions:
char & at (size_t pos); // non-const member function
const char & at (size_t pos) const; // const member function
A const string object will invoke the const version, which returns a const char & that cannot be used a lvalue.
const string str1("hello"); // const string object
cout << str1.at(1); // okay
str1.at(1) = 'x'; // error - returned const char & cannot be lvalue
string str2("again"); // non-const string object
str2.at(1) = 'x'; // okay
Pointer
Non-constant pointer to constant data: Data pointed to CANNOT be changed; but pointer CAN be changed to point to another data. For example,int i1 = 8, i2 = 9;
const int * iptr = &i1; // non-constant pointer pointing to constant data
// *iptr = 9; // error: assignment of read-only location
iptr = &i2; // okay
Constant pointer to non-constant data: Data pointed to CAN be changed; but pointer CANNOT be changed to point to another data. For example,
int i1 = 8, i2 = 9;
int * const iptr = &i1; // constant pointer pointing to non-constant data
*iptr = 9; // okay
// iptr = &i2; // error: assignment of read-only variable
Constant pointer to constant data: Data pointed to CANNOT be changed; and pointer CANNOT be changed to point to another data. For example,
int i1 = 8, i2 = 9;
const int * const iptr = &i1; // constant pointer pointing to constant data
// *iptr = 9; // error: assignment of read-only variable
// iptr = &i2; // error: assignment of read-only variable
Non-constant pointer to non-constant data: Data pointed to CAN be changed; and pointer CAN be changed to point to another data. For example,
*, the pointer itself is a constant.
Comments
Post a Comment