In general programming, variables are objects whose value can change – objects that can vary. This is in contrast with constants, whose value cannot change.

Variables are fundamental to programming, because without them, a program’s behaviour could not change – it would run the same way every time – and even simple programs would require enormous amounts of memory because, if objects’ values cannot change, each new value needed would need a new object.


Variables in C++

In C++, a variable is actually just a bit of memory that has been reserved for the program’s use. You refer to it using a variable name, so you don’t need to worry about where it is in memory (though you can find out its memory address, and even specify its location, if you want). The C++ type system keeps track of the size of the memory block, and how to interpret the value in it (that is, it will know whether the value 65 in a certain memory block actually refers to the number 65, the letter ‘A’ (the ASCII/Unicode code number for the character ‘A’ is 65), or even perhaps a complex number with real part 6 and imaginary part 5).

To create a variable in C++, you need at least two things: a name and a type.


Variable names are identifiers. Identifiers are labels used for various things in C++, including functions, classes, and namespaces as well as variables.

The rules for identifiers are the same whether the identifier refers to a variable, function, or whatever else. Identifiers can be pretty much whatever you like, taking into account a few rules. In general, the name of an identifier must consist of the characters a-z, A-Z, 0-9 and _, not begin with a digit or _ and not be a keyword. There are more rules that must be followed. You can read about them here.

Identifiers are usually not stored in the final program – unless you use certain debugging settings – so you don’t have worry about descriptive names giving hackers clues. You also don’t have to worry about the size of identifiers; if they’re stripped out, they take up no space in the final program.


C++ is a strongly-typed language, which means that when you say a variable is an integer, it stays an integer. This is unlike weakly-typed languages like Javascript/ECMAScript, where variables can change types.

The two reasons for this are efficiency and safety. If you allow variable’s types to change, you must keep track of what type a variable currently is, which has a cost. Keeping types fixed eliminates that cost. As for safety, consider this: in Javascript, if variable a equals 1 and variable b equals 2, and both are integers, then “a + b” gives 3... if both are text strings, “a + b” gives 12... but what do you get if one is an integer and one is a string? You could make up rules to answer the question, but that just makes things more complicated. It is safer to require programmers to explicitly say whether they want to add two integers or two strings. Type safety is a very important feature of C++, that makes your code efficient and easy to predict how it will behave.

There are several fundamental types in C++ – the exact number depends on the version. Here are some of the more basic ones:

  • Signed integer types, which can hold positive and negative whole numbers. The basic signed integer type is int, which can hold at least −32,767 to 32,767.
  • Unsigned integer types, which can hold only positive whole numbers. The basic unsigned integer type is unsigned int, which can hold at least 0 to 65,535.
  • Character types, which can hold characters, including letters, digits, punctuation, spaces, and control codes (like newline and tab). The basic character type is char, which is guaranteed to hold at least all upper and lowercase Latin letters (‘a’ – ‘z’ and ‘A’ – ‘Z’) and digits (‘0’ – ‘9’), some basic punctuation (‘{’, ‘}’, ‘[’, ‘]’, ‘#’, ‘(’, ‘)’, ‘<’, ‘>’, ‘%’, ‘:’, ‘;’, ‘.’, ‘?’, ‘*’, ‘+’, ‘-’, ‘/’, ‘^’, ‘&’, ‘|’, ‘’, ‘!’, ‘=’, ‘,’, ‘\’, ‘"’, ‘'’, ‘_’), and some control codes (like carriage return, newline, tab, and null).
  • Floating point types, which store real numbers in two parts – a mantissa and an exponent.

For example, it would rewrite 1.25 as 1.25×10⁰, then store it as {1.25, 0}; 0.00434.3×10⁻³ → {4.3, −3}; −250002.5×10⁴ → {−2.5, 5}. This enables the storage of huge or tiny numbers, but with limited precision (few significant digits). The basic floating point type is double. The limits of floating point numbers is a complicated topic, but double is guaranteed to hold positive values as large as at least 1.79769313486231571×10³⁰⁸ and at least as small as 2.22507385850720138×10⁻³⁰⁸.

Note that the limits given are just the minimum limits. On some systems, the limits can be much greater. For example, on 32-bit systems, the range of an int is usually −2,147,483,648 to 2,147,483,647.

C++ also includes dozens of types in its standard library, like std::string to hold text strings and std::vector to hold multiple values.

Creating variables

C++ requires you to declare all variables before you use them – it does not allow variables to appear out of nowhere. However, C++ is flexible about where you can declare them.

To create a variable for use, the normal syntax is:

<type> <identifier> = {<initializer>};

For example, to create an integer variable named “value” with an initial value of 42, you would write:

int value = {42};

Here are some other examples of creating variables:

// A variable storing the mass of the Earth (5.97219x10^24 kg)
double mass_of_earth = { 5.97219e24 };
// Create a text string with the URL of the site.
std::string site_url = {""};
// Create a vector holding the first 5 positive odd numbers.
// Note that it doesn’t all have to be on one line, which is handy
// if you have a long list.
std::vector<int> odd_numbers = {
    1, 3, 5, 7, 9

If you leave the braces empty, the variable will be default-constructed – that is, created with its default value. For fundamental types like int and double, the default value is zero. Default-constructed strings and vectors are empty (zero length strings and vectors with no items in them).

int v1 = {}; // initialized to 0
double v2 = {}; // initialized to 0.0
std::string v3 = {}; // initialized to a zero-length string
std::vector<int> v4 = {}; // initialized to an empty vector

When creating a variable, the equal sign is optional:

int value{42};
double v{};
std::string s{};
std::vector<int> odd_numbers{ 1, 3, 5, 7, 9 };

In some cases, the braces are optional (if you drop them, you must include the equal sign), or you can use parentheses instead, but this may subtly change the meaning in surprising ways:

int i = 42; // Same as "int i = {42};"
double d = 6.28; // Same as "double d = {6.28};"
string s = "Hello, world!"; // Same as "string s = {"Hello, world!"};"
// This doesn't work
//std::vector<int> v = 1, 3, 5, 7, 9;
//int i1{6.28}; // causes an error, because 6.28 is not an integer
int i2(6.28); // truncates 6.28 to an integer, so same as "int i2 = {6};"
std::vector<int> v1{3, 5}; // creates a vector with 2 values: {3, 5}
std::vector<int> v1(3, 5); // creates a vector with 3 values: {5, 5, 5}

Unless you intend to specifically call a class’s constructor (which will be covered later) or to force a value to fit in a type (like cramming 6.28 into an int), it is better not to use parentheses. In cases where the braces are optional, whether to use them or not is usually a style choice.

Using variables

Reading the value stored in a variable is as easy as simply using the variable’s name in an expression.

To change the value in a variable, you have to put the variable on the left-hand side of an assignment operator. The most basic assignment operator is just the equal sign (‘=’), which assigns the result of whatever is on the right-hand side into the variable.

#include <iostream>
int main()
    // Create the variable, then read its value and print it.
    int v1 = 42;
    std::cout << v1 << '\n';
    // Change the variable value, then read & print it.
    v1 = 69;
    std::cout << v1 << '\n';
    // You can even use expressions to create a value.
    double temp_in_F = 72;
    double temp_in_C = (temp_in_F - 32) / 1.8;
    std::cout << temp_in_F << "degrees Fahrenheit is " <<
               temp_in_C << "degrees Celsius " << '\n';
    // You can even use expressions when changing a variable, too.
    temp_in_F = 95.5;
    temp_in_C = (temp_in_F - 32) / 1.8;
    std::cout << temp_in_F << "degrees Fahrenheit is " <<
               temp_in_C << "degrees Celsius " << '\n';
    return 0;

Type deduction

Starting with C++11, C++ is now smart enough to figure out the types for variables automatically. For example, if you use an integer value like 42, C++ can figure out that you want an int; if you use a decimal value like 6.28, C++ can figure you that you don’t want an int, you want a double.

To get type deduction, you can use auto as the variable type:

auto a = 42;   // the type of a is deduced as int
auto b = 6.28; // the type of b is deduced as double

You can then use these variables as if they were created normally. (In other words, there is no difference between “auto a = 42;” and “int a = 42;”.)

Type deduction even works when initializing from expressions or other variables:

// This deduces the type as double,
// because of the decimal point.
auto height_in_cm = 170.0;
// This deduces the type as double,
// because height_in_cm is double.
auto height = height_in_cm;
// This deduces as double, because the
// expression is {double * double}
auto height_in_ft = height_in_cm * 0.032808399;
// This deduces as double, even though 10 is an int,
// because {int * double} = double.
auto height_in_mm = height_in_cm * 10;

Unless you need to know the type of a variable for some reason, type deduction frees you from having to keep track of variables for type safety.

Recently, a C++ expert has begun recommending a style called AAA – Almost Always Auto:

// Creating variables normally:
auto v1 = /* initializer (maybe without braces when possible) */;
// Creating variables when you want a specific type:
auto v2 = /*type*/{/* initializer or empty for default */};
// Creating variables when you want to FORCE a specific type,
// OR when you want to explicitly use a certain constructor:
auto v3 = /*type*/(/* initializer or empty for default */);


auto meaning_of_life = 42;
auto speed_of_light = 299.8e6;
auto site_url = std::string{""};
auto planet_masses = std::vector<double>{

This makes creating variables in C++ simple and uniform, freeing you from having to worry about the type system most of the time, while also getting the benefits of type safety.