C++ Beginner

cpp_021: Const Modifier in C++

codeaddict 2025. 4. 5. 20:00

In C++, the const keyword is a powerful tool for controlling how data is used in your program. It allows you to declare variables, parameters, or return values as “constant,” meaning they cannot be modified after initialization. This is crucial for writing safe, predictable code — especially when passing data to functions. In this post, we’ll explore const in a general sense, using examples with variables, arrays, and function interactions to show how it enforces read-only behavior and what happens when we mix const and non-const contexts.

1. Basics of const with Variables

Let’s start simple. The const keyword makes a variable immutable after it’s initialized.

#include <iostream>
using namespace std;

int main() {
    const int x = 5; // x is constant
    // x = 10; // Error: assignment of read-only variable 'x'
    cout << "x = " << x << endl;

    int y = 20; // y is not constant
    y = 30; // Perfectly fine
    cout << "y = " << y << endl;

    return 0;
}

Output:

x = 5
y = 30
  • Key Point: const int x can’t be changed after initialization, but y (non-const) can. This is the foundation of const: it locks a value in place. This highlights the purpose of const: it locks a value in place to prevent changes. If you attempt to modify x, the compiler will throw an error, as shown in the commented line within the code.

2. Using const in Function Parameters

When you pass data to a function, const ensures the function can’t modify it. Let’s see this with a scalar (single value) and then an array.

Example 1: Scalar Parameter

#include <iostream>
using namespace std;

void printValue(const int x) {
    // x = 50; // Error: assignment of read-only parameter 'x'
    cout << "Inside function, x = " << x << endl;
}

int main() {
    int a = 10;
    printValue(a); // Pass a to the function
    a = 20; // Change a outside the function
    cout << "Outside function, a = " << a << endl;

    return 0;
}

Output:

Inside function, x = 10
Outside function, a = 20

What’s Happening?

  • const int x is a copy of a. The function can’t modify x, but since it’s a copy, the original a isn’t affected anyway.
  • Outside the function, a is non-const, so we can change it freely.

Example 2: Array Parameter

Arrays are passed as pointers, not copies, so const becomes more critical.

#include <iostream>
using namespace std;

void printArray(const int arr[], int size) {
    // arr[0] = 100; // Error: assignment of read-only location
    for (int i = 0; i < size; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

int main() {
    int numbers[] = {1, 2, 3, 4};
    int size = 4;

    printArray(numbers, size); // Array is read-only inside function
    numbers[0] = 10; // Modify outside function
    cout << "After modification: ";
    printArray(numbers, size);

    return 0;
}

Output:

1 2 3 4
After modification: 10 2 3 4

Key Point:

  • const int arr[] prevents the function from modifying the array’s elements.
  • Outside the function, numbers is non-const, so we can still change it. The const restriction only applies inside printArray.

3. const Inside vs. Outside Functions

The const keyword’s scope is local to where it’s applied. Data that’s const inside a function can still be modified outside if it’s not declared const there. Let’s explore this further.

Example 3: Mixing const and Non-const

#include <iostream>
using namespace std;

void processData(const int value, const int arr[], int size) {
    cout << "Value = " << value << ", Array = ";
    for (int i = 0; i < size; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

int main() {
    int num = 5;
    int data[] = {10, 20, 30};

    processData(num, data, 3); // Pass non-const data to const parameters

    num = 15; // Modify num
    data[0] = 100; // Modify data
    cout << "After changes: ";
    processData(num, data, 3);

    return 0;
}

Output:

Value = 5, Array = 10 20 30
After changes: Value = 15, Array = 100 20 30

Explanation:

  • Inside processData, value and arr are const, so the function can’t change them.
  • Outside, num and data are non-const, so we can modify them freely. The const in the function doesn’t “lock” the original data — it just restricts what the function can do.

4. Challenges with const and Function Calls

What happens if a function with const parameters needs to call another function? If the second function doesn’t expect const data, you’ll run into issues. Let’s see this in action.

Example 4: Calling a Non-const Function

#include <iostream>
using namespace std;

void modifyArray(int arr[], int size) { // Non-const parameter
    arr[0] = 999;
    cout << "Modified in modifyArray: " << arr[0] << endl;
}

void processArray(const int arr[], int size) {
    cout << "In processArray: " << arr[0] << endl;
    // modifyArray(arr, size); // Error: cannot convert 'const int*' to 'int*'
}

int main() {
    int numbers[] = {1, 2, 3};
    processArray(numbers, 3);
    modifyArray(numbers, 3); // Works fine here
    processArray(numbers, 3);

    return 0;
}

Output:

In processArray: 1
Modified in modifyArray: 999
In processArray: 999

Problem:

  • processArray takes const int arr[], so arr is read-only. => Because of this, you cannot call modifyArray(arr, size) from within processArray. The reason is that modifyArray expects a non-const array (int arr[]), which it modifies. => The compiler prevents this with an error like: Error: cannot convert ‘const int*’ to ‘int*’”.
 

Conclusion

The const modifier in C++ is all about control. It lets you:

  • Protect data inside functions from being modified (const int x, const int arr[]).
  • Keep flexibility outside functions where data isn’t const.

Whether you’re working with scalars, arrays, or multi-dimensional structures, const helps you write safer, more intentional code. It’s especially valuable in large projects where tracking modifications can get messy.