In C++, the keyword `const` is used to indicate that a function parameter, particularly a pointer, should not be used to modify the data it points to. This ensures that the function can read the data pointed to by the pointer, but cannot change it. Using `const` with pointers in function arguments can be done in two primary ways:
- Pointer to Constant Data: This declares that the data being pointed to will not be modified by the function. The syntax is `const Type* pointerName`, where `Type` is the data type of the variable the pointer points to.
- Constant Pointer: This declares that the pointer itself cannot be changed to point to a different memory location, although the data it points to can be modified. The syntax is `Type* const pointerName`.
Here's an example demonstrating both usages in the context of a function:
#include <iostream>
// Function with a pointer to constant data
void printArray(const int* arr, int size) {
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << " ";
// arr[i] = i; // This line would cause a compilation error
}
std::cout << "\n";
}
// Function with a constant pointer
void incrementAll(int* const arr, int size) {
for (int i = 0; i < size; ++i) {
arr[i]++;
}
// arr = nullptr; // This line would cause a compilation error
}
int main() {
int numbers[] = {1, 2, 3, 4, 5};
int size = sizeof(numbers) / sizeof(numbers[0]);
printArray(numbers, size); // Prints the array elements
incrementAll(numbers, size); // Increments each element by 1
printArray(numbers, size); // Prints the modified array elements
return 0;
}
In `printArray`, `const int* arr` means the function can use `arr` to read the array elements but cannot modify them. In `incrementAll`, `int* const arr` means the function can modify the elements pointed by `arr` but cannot change the `arr` pointer to point elsewhere. This usage of `const` improves code readability and safety, indicating the intended use of the pointers to other developers and to the compiler.
const type * identifier
declares the identifier as a pointer whose pointed at value is constant.
This construct is used when pointer arguments to functions will not have their contents modified.
So
void fcn(const int* p){
// within here it is illegal
// to have *p = expression;
}
This provides "
const
safety" allowing the compiler to detect an error.
It also allows the compiler to optimize how these arguments are passed.
-
Non-const pointers
Let us contrast this with a non-const
pointer argument:
void fcn(int* p){
// within here it is legal
// to have *p = expression;
}
Now attempting to pass a const
pointer value will lead to a syntax error.
const int size = 100; //size may not be modified
fcn(&size); //illegal because the address
// of a const variable is being passed to an
// argument that allows for modification
// of what is pointed at.
We can take this one step further. The form
const type* const identifier
declares the identifier as a
Pointer Constant Example
The statement
const int* const cp;
declares
cp
to be a constant pointer whose pointed-at value is also constant.
void fcn(const int* const p){
// within here it is illegal
// to have *p = expression;
// also illegal is p = expression;
}
const char* pstars[] {
"Fatty Arbuckle", "Clara Bow",
"Lassie", "Slim Pickens",
"Boris Karloff", "Mae West",
"Oliver Hardy", "Greta Garbo"
};
Here you are specifying that the objects pointed to by elements of the array are constant. The compiler inhibits any direct attempt to change these, so an assignment statement such as this would be flagged as an error by the compiler, thus preventing a nasty problem at runtime:
*pstars[0] = 'X'; // Will not compile...
However, you could still legally write the next statement, which would copy the address stored in the element on the right of the assignment operator to the element on the left:
pstars[5] = pstars[6]; // OK
Those lucky individuals due to be awarded Ms. West would now get Mr. Hardy, because both pointers now point to the same name. Of course, this has not changed the object pointed to by the sixth array element, it has only changed the address stored in it, so the const specification has not been breached. You really ought to be able to inhibit this kind of change as well, because some people may reckon that good old Ollie may not have quite the same sex appeal as Mae, and of course you can.
Look at this statement:
const char* const pstars[] {
"Fatty Arbuckle", "Clara Bow",
"Lassie", "Slim Pickens",
"Boris Karloff", "Mae West",
"Oliver Hardy", "Greta Garbo"
};
Here are some other examples of
const
variable declaration:
const double pi = 3.14159;
double x = 1.5;
const double *d_p1 = π //legal
double *d_p2 = &x; //legal
const double *d_p2 = &3.1; //illegal:3.1 is not an lvalue
pi = 3.141596; //illegal: pi cannot be modified
d_p1 = &x; //legal: safe conversion
d_p2 = π //illegal: would allow a const to be modified through a non-const pointer