The const keyword is one of the most useful tools you will learn as a beginner in C++. It marks values as read-only through a given expression so you (or other parts of the program) cannot accidentally modify them. In this quick guide to “C++ const keyword with examples,” you will learn what const means, how to use it in variables, parameters, references, pointers, and member functions, along with common mistakes to avoid. If you are a student or new to C++, mastering const will immediately make your code safer and clearer.
- const makes a value read-only through that expression; it is not automatically a compile-time constant.
- Prefer const T& for large function parameters to avoid copies and prevent mutation.
- Mark member functions that don’t change observable state as const to preserve const-correctness.
- Use constexpr for true compile-time constants; constinit (C++20) for guaranteed static initialization.
- For pointers/references, remember: “const applies to what’s on its left (or right if nothing is on the left).”
What does const mean in C++?
In C++, const is a type qualifier. It tells the compiler that something cannot be changed through that expression. For example, a const int variable cannot be assigned a new value after it is initialized.
Important: const by itself does not mean “compile-time constant.” A const variable can still hold a value that is only known at runtime. For true compile-time constants you usually use constexpr (explained later).
Example: Simple const variable
#class="cd-package">include <iostream>
int main() {
const int maxScore = 100; // read-only after this point
std::cout << "Max score: " << maxScore << "n";
// maxScore = 200; // Uncommenting this line would cause a compile error
return 0;
}Max score: 100Why beginners should use const
- Prevents accidental changes to values that should not change (safer code).
- Documents your intent clearly for readers and tools.
- Enables const-correct APIs (easier to reason about and maintain).
- Can help the compiler optimize in some cases.
How to use const in C++ (basic syntax)
Most commonly, you will see const used with variables and function parameters.
C++ const variables
#class="cd-package">include <iostream>
#class="cd-package">include <string>
int readUserAge() {
int age;
std::cin >> age;
return age;
}
int main() {
std::cout << "Enter age: ";
const int userAge = readUserAge(); // const, but not necessarily compile-time constant
std::cout << "Your age is: " << userAge << "n";
// userAge = 21; // would be an error if uncommented
return 0;
}Enter age: 20
Your age is: 20Const parameters: by value vs by reference
When passing by value, marking a parameter as const only affects the function’s local copy; it doesn’t change how the caller can use their original value. For larger objects, prefer passing by const reference (const T&) to avoid copying while still protecting against modification.
#class="cd-package">include <iostream>
#class="cd-package">include <string>
void printLenByValue(const std::string s) { // const applies only inside the function
std::cout << "Length (by value): " << s.size() << "n";
}
void printLenByConstRef(const std::string& s) { // no copy, cannot modify s
std::cout << "Length (by const ref): " << s.size() << "n";
}
int main() {
std::string name = "CodDesire";
printLenByValue(name); // copies ___CDPHSTR5___
printLenByConstRef(name); // no copy
// Works with temporaries too (lifetime handled by the call):
printLenByConstRef(std::string("C++ Learner"));
return 0;
}Length (by value): 9
Length (by const ref): 9
Length (by const ref): 11Const with pointers and references
This is where many beginners get confused. A helpful rule to read declarations is: “const applies to what’s on its left (or right if there’s nothing on the left).”
- const int* p — pointer to const int (you can’t modify the int via p).
- int* const p — const pointer to int (pointer cannot change, but the int can).
- const int* const p — const pointer to const int.
Pointers and references: const cheat sheet (quick reference)
| Declaration | Meaning | Modify pointee? | Reseat pointer? | Examples |
|---|---|---|---|---|
const int* p or int const* p |
Pointer to const int | No | Yes | *p = 5; // errorp = &other; // ok |
int* const p |
Const pointer to int | Yes | No | *p = 5; // okp = &other; // error |
const int* const p |
Const pointer to const int | No | No | *p = 5; // errorp = &other; // error |
const int& r |
Reference to const int | No | N/A (references don’t reseat) | r = 5; // errorbinds to temporaries // ok |
Example: Pointers to const and const pointers
#class="cd-package">include <iostream>
int main() {
int value = 10;
const int* p1 = &value; // pointer to const int (can't modify *p1)
// *p1 = 20; // error if uncommented
p1 = &value; // can reseat p1
int* const p2 = &value; // const pointer to int (can't reseat p2)
*p2 = 20; // but can modify the pointee
// p2 = &value; // error if uncommented
const int* const p3 = &value; // const pointer to const int
// *p3 = 30; // error if uncommented
// p3 = &value; // error if uncommented
std::cout << "value: " << value << "n";
return 0;
}value: 20Const reference in C++ explained
A const reference (const T&) can bind to both lvalues and temporaries (rvalues). When a temporary is bound directly to a const reference, its lifetime is extended to match the reference’s lifetime. This is both efficient and safe for function parameters and local bindings.
Example: Lifetime extension with const reference
#class="cd-package">include <iostream>
#class="cd-package">include <string>
std::string make_full_name() {
return "Ada Lovelace";
}
int main() {
const std::string& ref = make_full_name(); // temporary bound to const ref; lifetime extended
std::cout << ref << "n"; // safe to use
return 0;
}Ada LovelaceC++ const functions and methods (const member function example)
In classes, mark methods that do not change the object’s observable state as const. This lets you call them on const objects and documents that they won’t modify members (unless they are marked mutable).
Example: const member function
#class="cd-package">include <iostream>
class Counter {
int value_ = 0;
class="cd-keyword cd-access">public:
void increment() { ++value_; }
int value() const { return value_; } // does not modify the object
};
int main() {
Counter c;
c.increment();
c.increment();
std::cout << "Value: " << c.value() << "n";
const Counter cc = c;
std::cout << "Const view: " << cc.value() << "n";
// cc.increment(); // would be an error: cannot call non-const on const object
return 0;
}Value: 2
Const view: 2When should I use const in C++ code?
- Constants and configuration that should not change after initialization: const int Max = 10;.
- Function parameters for large objects: prefer const T& to avoid copies and disallow mutation.
- Getters and query-like member functions: mark them const.
- Local variables you do not intend to modify: using const reduces mistakes and clarifies intent.
- Pointers and references: use const to prevent mutation through that access path.
Note: Adding const to a parameter passed by value doesn’t affect the caller and is mostly a local choice. Prefer const references for expensive-to-copy types instead.
Difference between const and constexpr (and constinit, #define)
Beginners often ask for a “difference between const and constexpr in C++ simple explanation.” Here’s a quick comparison along with #define and constinit:
| Feature | What it means | When to use | Notes |
|---|---|---|---|
| const | Read-only through that expression | Protect variables, parameters, references, members from mutation | Not necessarily a compile-time constant |
| constexpr | Must be initialized with a constant expression; usable at compile time | True compile-time constants (sizes, array bounds, switch cases) | Functions can also be constexpr; evaluated at compile time when possible |
| constinit (C++20) | Ensures static/thread storage variables are initialized at compile time | Globals with guaranteed initialization order and speed | Variable remains mutable unless also const |
| #define | Preprocessor macro (text replacement) | Legacy constants or conditional compilation | No type safety or scope; prefer constexpr/const |
How to choose: const, const&, constexpr, constinit
If not strictly compile-time → use const.
Large/expensive to copy → pass const T&.
Otherwise → non-const.
Examples: const vs constexpr vs constinit
#class="cd-package">include <iostream>
#class="cd-package">include <ctime>
// Prefer constexpr for real compile-time constants:
constexpr int DaysInWeek = 7;
// const can be runtime-initialized:
int runtime_value() { return std::time(nullptr) % 10; }
const int ModValue = runtime_value(); // not a compile-time constant
// constinit (C++20) ensures compile-time initialization for statics:
constinit int GlobalCount = 0; // still mutable unless also const
int main() {
std::cout << "DaysInWeek: " << DaysInWeek << "n";
std::cout << "ModValue: " << ModValue << "n";
GlobalCount += 1; // allowed
std::cout << "GlobalCount: " << GlobalCount << "n";
return 0;
}DaysInWeek: 7
ModValue: 3
GlobalCount: 1Common mistakes and how to avoid them
- Thinking “const means compile-time constant.” Use constexpr for compile-time constants; const alone can be runtime-initialized.
- Using const on by-value parameters to “protect the caller.” Top-level const on a copy affects only the function body, not the caller.
- Forgetting to mark read-only member functions as const. This blocks use on const objects and weakens const-correctness.
- Assuming const implies thread safety. A const function may still read shared state or modify mutable members; thread safety is a separate concern.
- Abusing const_cast. Casting away const and then modifying an object originally declared const results in undefined behavior.
- Making many data members const to “freeze” the object. This can prevent move/assignment and complicate types. Prefer const-correct interfaces instead.
C++ const keyword explained for beginners: a quick practice
Here’s a small program that brings together const variables, const references, and const member functions.
#class="cd-package">include <iostream>
#class="cd-package">include <string>
class Student {
std::string name_;
int score_ = 0;
class="cd-keyword cd-access">public:
Student(std::string name, int score) : name_(std::move(name)), score_(score) {}
void addBonus(int bonus) { score_ += bonus; } // mutates
// const member function: safe to call on const objects
std::string name() const { return name_; }
int score() const { return score_; }
};
void printStudent(const Student& s) { // const reference: no copy, no mutation
std::cout << s.name() << " has score " << s.score() << "n";
}
int main() {
const int Bonus = 5; // read-only constant value
Student s("Riya", 90);
s.addBonus(Bonus);
const Student cs = s; // const view of the same student
printStudent(cs); // calls only const member functions
// cs.addBonus(10); // would be an error if uncommented
return 0;
}Riya has score 95People also ask: quick FAQ
What does the const keyword do in C++?
const marks an object as read-only through that expression. You cannot modify a const object or call non-const member functions on it. This helps you write safer, clearer code.
When should I use const in C++ code?
Use const for values that shouldn’t change, for function parameters passed by const reference, and for class methods that don’t modify the object’s state. This is the essence of const-correctness.
How do I write a const variable or parameter in C++?
Variables: const int x = 10;. Parameters: void f(const std::string& s). For pointers: const int* p (pointer to const int) and int* const p (const pointer to int).
What is a const member function in C++ and why use it?
A const member function guarantees it won’t modify the object’s observable state. It lets you call the function on const objects and communicates intent clearly.
What is the difference between const, constexpr, and #define in C++?
const prevents modification at runtime; constexpr creates compile-time constants (when used with constant expressions); #define is a preprocessor macro without type safety or scope. Prefer constexpr or const over #define for constants.
More examples: const parameter and reference
Below is a compact “how to declare const variables in C++ with example” and “C++ const parameter and reference example.”
#class="cd-package">include <iostream>
#class="cd-package">include <vector>
int sum(const std::vector<int>& v) { // const reference: no copy, read-only
int total = 0;
for (int x : v) total += x;
return total;
}
int main() {
const int limit = 4; // const variable
std::vector<int> data = {1, 2, 3, 4};
std::cout << "Limit: " << limit << ", Sum: " << sum(data) << "n";
return 0;
}Limit: 4, Sum: 10Tips for reading const with pointers
- Read right-to-left at the identifier: int* const p — “p is a const pointer to int.”
- const int* p — “p is a pointer to const int.”
- Use parentheses when in doubt to clarify intent.
Where to learn next
Keep practicing “C++ const keyword with examples” alongside related topics like references, pointers, and classes. Explore more C++ tutorials on CodDesire here: C++ Tutorials at CodDesire.


