D.2.9 — Const, constexpr, and symbolic constants

Const variables

So far, all of the variables we’ve seen have been non-constant -- that is, their values can be changed at any time. For example:

However, it’s sometimes useful to define variables with values that can not be changed. For example, consider the value of gravity on Earth: 9.8 meters/second^2. This isn’t likely to change any time soon. Defining this value as a constant helps ensure that this value isn’t accidentally changed.

To make a variable constant, simply put the const keyword either before or after the variable type, like so:

Although C++ will accept const either before or after the type, we recommend using it before the type because it better follows standard English language convention where modifiers come before the object being modified (e.g. a green ball, not a ball green).

Const variables must be initialized when you define them, and then that value can not be changed via assignment.

Declaring a variable as const prevents us from inadvertently changing its value:

Defining a const variable without initializing it will also cause a compile error:

Note that const variables can be initialized from non-const values:

Const is used most often with function parameters:

Making a function parameter const does two things. First, it tells the person calling the function that the function will not change the value of myValue. Second, it ensures that the function doesn’t change the value of myValue.

With parameters passed by value, like the above, we generally don’t care if the function changes the value of the parameter (since it’s just a copy that will be destroyed at the end of the function anyway). For this reason, we usually don’t const parameters passed by value. But later on, we’ll talk about other kinds of function parameters (where changing the value of the parameter will change the value of the argument passed in). For these types of parameters, judicious use of const is important.

Compile time vs runtime

When you are in the process of compiling your program, that is called compile time. During compile time, the compiler ensures your code is syntactically correct, and converts your code into object files.

When you are in the process of running your application, that is called runtime. During runtime, your program executes line by line.


C++ actually has two different kinds of constants.

Runtime constants are those whose initialization values can only be resolved at runtime (when your program is running). Variables such as usersAge and myValue above are runtime constants, because the compiler can’t determine their values at compile time. usersAge relies on user input (which can only be given at runtime) and myValue depends on the value passed into the function (which is only known at runtime).

Compile-time constants are those whose initialization values can be resolved at compile-time (when your program is compiling). Variable gravity above is an example of a compile-time constant. Whenever gravity is used, the compiler can simply substitute the identifier gravity for the literal double 9.8.

In most cases, it doesn’t matter whether a constant value is runtime or compile-time. However, there are a few odd cases where C++ requires a compile-time constant instead of a run-time constant (such as when defining the length of a fixed-size array -- we’ll cover this later). Because a const value could be either runtime or compile-time, the compiler has to keep track of which kind of constant it is.

To help provide more specificity, C++11 introduced new keyword constexpr, which ensures that the constant must be a compile-time constant:

Rule: Any variable that should not change values after initialization and whose initializer is known at compile-time should be declared as constexpr.
Rule: Any variable that should not change values after initialization and whose initializer is not known at compile-time should be declared as const.

Note: Many of these tutorials were written before constexpr existed and have not been fully updated. In practical terms, this isn’t an issue, as constexpr is only required in specific situations.

Naming your const variables

Some programmers prefer to use all upper-case names for const variables. Others use normal variable names with a ‘k’ prefix. However, we will use normal variable naming conventions, which is more common. Const variables act exactly like normal variables in every case except that they can not be assigned to, so there’s no particular reason they need to be denoted as special.

Symbolic constants

In the previous lesson D.2.8 -- Literals, we discussed “magic numbers”, which are literals used in a program to represent a constant value. Since magic numbers are bad, what should you do instead? The answer is: use symbolic constants! A symbolic constant is a name given to a constant literal value. There are two ways to declare symbolic constants in C++. One of them is good, and one of them is not. We’ll show you both.

Bad: Using object-like macros with a substitution parameter as symbolic constants

We’re going to show you the less desirable way to define a symbolic constant first. This method was commonly used in a lot of older code, so you may still see it.

In lesson 2.10 -- Introduction to the preprocessor, you learned that object-like macros have two forms -- one that doesn’t take a substitution parameter (generally used for conditional compilation), and one that does have a substitution parameter. We’ll talk about the case with the substitution parameter here. That takes the form:

#define identifier substitution_text

Whenever the preprocessor encounters this directive, any further occurrence of ‘identifier’ is replaced by ‘substitution_text’. The identifier is traditionally typed in all capital letters, using underscores to represent spaces.

Consider the following snippet:

When you compile your code, the preprocessor replaces all instances of MAX_STUDENTS_PER_CLASS with the literal value 30, which is then compiled into your executable.

You’ll likely agree that this is much more intuitive than using a magic number for a couple of reasons. MAX_STUDENTS_PER_CLASS provides context for what the program is trying to do, even without a comment. Second, if the number of max students per classroom changes, we only need to change the value of MAX_STUDENTS_PER_CLASS in one place, and all instances of MAX_STUDENTS_PER_CLASS will be replaced by the new literal value at the next compilation.

Consider our second example, using #define symbolic constants:

In this case, it’s clear that MAX_STUDENTS_PER_CLASS and MAX_NAME_LENGTH are intended to be independent values, even though they happen to share the same value (30).

So why not use #define to make symbolic constants? There are (at least) two major problems.

First, because macros are resolved by the preprocessor, which replaces the symbolic name with the defined value, #defined symbolic constants do not show up in the debugger (which shows you your actual code). So although the compiler would compile int max_students = numClassrooms * 30;, in the debugger you’d see int max_students = numClassrooms * MAX_STUDENTS_PER_CLASS;. You’d have to go find the definition of MAX_STUDENTS_PER_CLASS in order to know what the actual value was. This can make your programs harder to debug.

Second, #defined values always have file scope (which we’ll talk more about in the section on local and global variables). This means a value #defined in one piece of code may have a naming conflict with a value #defined within the same file later.

For example:

In the above code, we #define x in function a(), intending it to be used inside function a(). However, #define value x can actually be used anywhere beyond that point in the same file. So when function b() #defines its own x, we get a naming conflict. Even if function b() used a variable named x instead of a #define value named x, we would still have issues, as the preprocessor would try to replace variable name x with the value 5.

Rule: Avoid using #define to create symbolic constants

A better solution: Use const variables

A better way to create symbolic constants is through use of const (or better, constexpr) variables:

These will show up in the debugger, and follow all of the normal variable rules around scope.

Rule: use const variables to provide a name and context for your magic numbers.

Using symbolic constants throughout a program

In many applications, a given symbolic constant needs to be used throughout your code (not just in one location). These can include physics or mathematical constants that don’t change (e.g. pi or avogadro’s number), or application-specific “tuning” values (e.g. friction or gravity coefficients). Instead of redefining these every time they are needed, it’s better to declare them once in a central location and use them wherever needed. That way, if you ever need to change them, you only need to change them in one place.

There are multiple ways to facilitate this within C++, but the following is probably easiest:

1) Create a header file to hold these constants
2) Inside this header file, declare a namespace (we’ll talk more about this in lesson 4.3b -- Namespaces)
3) Add all your constants inside the namespace (make sure they’re const)
4) #include the header file wherever you need it

e.g. constants.h:

Use the scope resolution operator (::) to access your constants in .cpp files:

If you have both physics constants and per-application tuning values, you may opt to use two sets of files -- one for the physics values that will never change, and one for your per-program tuning values that are specific to your program. That way you can reuse the physics values in any program.

Note: In lesson 4.2 -- Global variables and linkage, we show a more efficient way to do symbolic constants using global variables.

D.2.10 -- Chapter D.2 comprehensive quiz
D.2.8 -- Literals

165 comments to D.2.9 — Const, constexpr, and symbolic constants

  • Sal

    Whats the difference between compile time and runtime?

    • Alex

      Compile time happens when your compiler is compiling your program.
      Runtime happens when your program is executing.

      I've updated the lesson text to be more descriptive about what these are.

  • Rojava

    In header files, using your example, can we replace const with constexpr like this to help the compiler optimize things?

    • Alex

      In most cases, the compiler can figure out whether a const is a compile-time const or a run-time const, so explicitly using constexpr generally isn't needed. But does make your intentions slightly more obvious, so it doesn't hurt either.

  • Sihoo Joo

    IDE: Eclipse Mars2
    ISO: +14

    Hi Alex,

    I'm still having trouble, trying to grasp the clear difference between runtime constant and compile-time constant. I get the general idea but still there is grey area in my mind. Please see below code.

    #include <iostream>

    int main()
        int x = 5;
        constexpr int y = x;
        std::cout << y << std::endl;

        return 0;

    constexpr int y = x; <--- this results in the compile error, telling me to change it to 'constant'.

    Once I change it to 'const int y = x;', then it compiles and runs fine, so I'm assuming this is was supposed to be made runtime constant instead of compile-time constant.

    But my understanding is that shouldn't this be compile-time constant since the value of x will be assigned to the value of y in the compiling stage as opposed to the above examples of 'userAge' & 'myValue' where these two are input values after the file is run.

    So my contention is that shouldn't the y-value of my example be compile-time constant as it is assigned a value during the stage of compiling instead of running?

    If you can help me out, really appreciated :)

    • Alex

      Const int y = x is a runtime constant, not a compile time constant. The compiler doesn't know the specific value of x, so it can't resolve the evaluation at compile time. If you said something like constexpr int y = 5, then the compiler would be able to resolve this as a compile time constant, since it knows what value it resolves to at compile time.

  • Paul

    I'm wondering why you used parenthasees to initialize

    I thought uniform initialization was preferred. Do parenthasees do the same thing?

    • Alex

      I wrote much of the tutorials before C++11 was introduced, so some of the examples still use the implicit initialization form. For fundamental variables, they do the same thing. You should be familiar with all forms of initialization, but as a best practice, use uniform initialization if you can.

  • a

    Your reference to acceleration due to gravity on Earth should be updated to say 9.8 meters/second^2 (or similar)

  • BlueTooth4269

    Const is most useful (and most often used) with function parameters:

    Making a function parameter const does two things. First, it tells the person calling the function that the function will not change the value of x. Second, it ensures that the function doesn’t change the value of x.

    -Shouldn't either x or myValue be changed to reflect the fact that one refers to the other? The connection between the two doesn't seem obvious here, if you get what I mean.

  • Hey, @ALEX, why did you use curly brackets instead of round brackets when you assigned a value to a constant integer?lol...Can they be interchanged as per our wishes???

  • Danny

    Clearly explained...I got it after reading this tutorial

  • Patrick Krootjes

    The unit for gravity is meter/second^2

  • Thomas Keith


    From your tutorial:

    const int yenPerDollar(122);
    yenPerDollar = 123; // compiler error, can not change value of const variable

    Unlike non-const variables, their values cannot be changed once set.
    Rule: Any variable that should not change values after initialization should be declared as const.

    I am interpreting this as meaning that the program itself or any of its functions cannot change the value of the constVariable.  One could always update the value manually and recompile.

    For variables that are going to change perhaps every day, like variableFixedForOneDay in a market trading program, would you simply not use a const, even though the value should not change during a particular instance of the program, and then either have the user input the data for the day or have the program get that input from a website that provides it?  Is it possible to have const int variableFixedForOneDay set by input from said website each time the program is run, perhaps by having main() get the value and write it to a file that would be used by the program without recompiling every time the value changes?

    Your tutorials sound like it would only be a good idea to use const for avagadro's number, the number of grams in an ounce, cubic feet in a cubic meter, etc. (some things that are virtually never going to be changed.)

    Would something like this work?
    cout <<"Input the Yen/Dollar conversion rate." <<endl;
    int x
    cin x
    const yenPerDollar = x


    • Alex

      Right, const means the program can't update the value. The programmer could always update it and recompile.

      I agree, for variables that may change day to day, you would not want to use a constant (yenPerDollar is a poor example in this regard). For these, you'd want to pull the data from an external source (a file, the internet, the user, etc...)

      Things like chemistry or physics constants are perfect, as they are unlikely to change anytime soon (and if they do, we've got larger problems). :)

      And yes, you can initialize a const value as you suggest, should you desire.

  • Joseph

    I have my constant header file set up but I get the squiggly green line telling me "cannot open soure file "constants.h"" I made a header file directly from the new file tab in visual studio and chose new header file in visual c++.
    Any suggestions as to what I should do or look for to fix this?

  • Len

    This material really is fantastic.

    I created a constant header file similar to yours, but I added some precision to the constants.  It truncated some digits so I tried using the "setprecision" command.  This did not work.  Then I tried to add this to the header file and it would not even compile the code (I included iomanip).

    What is the proper way to insure that the constants in the header file have the correct precision?

    In header file:
        const double pi(3.14159265);

    In main program:
        std::cout << "pi = " << constants::pi << "\n";
    pi = 3.14159

    • Alex

      You are so close. std::setprecision(9) needs to be inside the std::cout statement:

  • brad

    "in the debugger you’d see int yen = dollars * YEN_PER_DOLLAR"
    Isn't the same true when using int const YEN_PER_DOLLAR to define YEN_PER_DOLLAR.
    Wouldn't you still see int yen = dollar * YEN_PER_DOLLAR, since the debugger shows the actual code?

  • By reading some books, I came to know that there is another keyword that is used to declare compile time constant(constexpr) variables. But I can't differentiate between them. Only thing I understood is that const variable's value can be assigned at runtime, but a constexpr variable needs its value assigned at compile time. Is that the only difference between those two?

    • Alex

      Yes, constexpr is new in C++11 (and expanded in C++14) that is used to define a variable or function as a compile-time constant rather than a runtime constant. That allows constexpr to be used in a few places where normal const variables are not. Probably the biggest benefit is the constexpr functions can replace macro functions (which are dangerous). Constexpr should (in theory) also help the compiler optimize things.

  • Mr D

    Joel said: "I’m failing to see the advantage of this over simply defining yenPerDollar as a regular old variable"

    Then Alex repled: "Normal local variables are subject to local scoping rules, meaning they can only be accessed in the block in which they are declared. If you needed to use the same constant in different blocks, you’d have to declare it in each place you need it (which is both redundant and puts your code at risk of mistakes)."

    I don't understand this!
    If i first declare (example below) a Normal local variable, that value of x is seen by all following code blocks. No need for "const".
    Could you please give us a simple code example of this? So, first a "broken" version which just uses good ol' Normal local variables, and then the fixed version using const?

    • Alex

      Your variable x isn't a normal local variable, it's a global variable. This global variable won't be visible in another file unless you do a forward declaration in each file you want to access it.

      If you declare these values as const and put them in a header, it's very easy to:
      1) Keep them all in one place (the header).
      2) #include them into any file you need them.
      3) Make sure you don't accidentally change them (that's what the const is for).

  • ranjeet


    Please explain, which memory section is used to store a const value.

  • Joel

    Sorry if this has been asked before, but from this I can see why symbolic constants prevent the nightmare caused by "magic numbers," but I'm failing to see the advantage of this over simply defining yenPerDollar as a regular old variable. As a true beginner, the difference between the two is completely lost on me. Thanks for any clarification you can provide!

    • cpplx

      as another true beginner id say that it adds a level of safety and convenience. otherwise, seems to be another example of how you can do the same thing in another way. and if that is the reason, I got it from the lessons so reread, maybe it will become clearer. also next page has a quiz which wants you to write a program with a constant. it might help you too.
      if above is not true id be ashamed of myself :)

    • Alex

      > I’m failing to see the advantage of this over simply defining yenPerDollar as a regular old variable

      You could define yenPerDollar as a regular old non-const local variable, but there would be two issues:
      1) Non-const variables can be inadvertently changed.
      2) Normal local variables are subject to local scoping rules, meaning they can only be accessed in the block in which they are declared. If you needed to use the same constant in different blocks, you'd have to declare it in each place you need it (which is both redundant and puts your code at risk of mistakes).

      In the constants.h header file example, we've set up that header file up in such a way that the constants can be defined in one place and then #included anywhere you need to use them. That minimizes redundancy and the chance for error, and maximizes ease of use.

  • cpplx

    I have to be THAT GUY again :\...
    one day when you wonder what to do with your time,
    you may consider changing the examples about constants with something that actually is a constant
    exchange rate of currencies are not constant and change all the time.

  • techsavvy....aye

      the yet on the first line?

  • Todd


    You're missing a closing parenthesis after 'compilation':
    "one that doesn’t take a substitution parameter (generally used for conditional compilation, and one that does have a substitution parameter."

    "Although a constant variable (Although constant variables) might seem like an oxymoron, they can be very useful in helping to document your code and avoid magic numbers." ('they' is plural, so it should refer to 'constant variables' (plural))

  • What's wrong?

  • Shubham

    While keeping symbolic constants inside header file, is it essential to keep them inside a separate namespace and then using scope operator to use them? What is we don't use separate namespace?

    • Alex

      If you don't keep them inside a separate namespace, those identifier names go into the global namespace, where they can collide with other names in the global namespace. So while it's not necessary, it's a good idea to use a separate namespace.

  • Twisted Code

    "Unlike macro symbolic constants, const variables can be debugged, and all you to control the scope of their existence. "
    I think you were typing faster than you were thinking. Your I/O buffer got empty! You need to upgrade that lime of yours.

  • Andrei

    Just wanted to say, thanks for your ongoing work on this website, it's easily the best source for C++ learning and continues to develop.

  • Beginner

    Please let me know how memory is allocated in #define and const?
    What is the difference?

    • Alex

      No memory is allocated for #define values, because they are just text substitutions done by the preprocessor.

      Memory may or may not be allocated by using a const variable, depending on how you use it. Generally, this isn't something you'll need to worry about, as the amount of memory used by const variables is likely to be negligible.

  • marjoonjan

    What happen if we use ';' after the #define? See below for example:


    #define MAX 100;

    using namespace std;

    cout << MAX+2 << ' ' << 4+9;

    cout dose not print the result of the 4+9! why?

    • It simply makes the semicolon part of the definition, meaning that using the 'MAX' would automatically end the statement.
      Also, your code should give you a compiler error.

    • Darren

      This will compile with the requisite include <iostream> and int before main; zingmars' assessment is correct. This highlights the danger of using pre-processor defines in this way, and why you probably shouldn't use them in your code.

  • great guy

    what if you intalize a const varible, but don't assign it a value right away?

    • Mac

      it doesnt work and gives an error :
      error: uninitialized const 'nYenPerDollar'

      if you try to assign it later it says :
      error: assignment of read-only variable 'nYenPerDollar'

  • Ravi

    How about const with respect to functions?

  • Ronnie

    Did constants apply through the whole file? Or what? :S I mean const values using the


    • Const variables have the same scoping rules as normal variables. If you declare them globally, they apply though the whole file. If you declare them locally, they will die when they go out of scope. The only difference is that the value of a const variable can't be changed after initialization.

  • Skylark

    Could you not #define nYenPerDollar in a header file which is included in the main source code?

    This would eliminate the inconvenience of having to search for its place of definition and would also prevent the confict you mentioned.

    -- Just a thought. I'm completely new to C++ and object-oriented programming all together, just trying to get my head around how many different ways the same task can be completed in C++.

    PS: I am loving this tutorial. I'm using it for m pre-University study. =D

    • You could #define nYenPerDollar in a header file, but as I mentioned in the tutorial, #define values don't show up in the debugger, which can make them hard to debug, especially if you code uses them heavily. Since the concept of yen per dollar is a global concept (it's going to remain constant throughout the program) the fact that all #define values are global isn't much of a problem in this case.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]