Search

1.4 — Variable assignment and initialization

In the previous lesson (1.3 -- Introduction to variables), we covered how to define a variable that we can use to store values. In this lesson, we’ll explore how to actually put values into variables and use those values.

As a reminder, here’s a short snippet that first allocates a single integer variable named x, then allocates two more integer variables named y and z:

Variable assignment

After a variable has been defined, you can give it a value (in a separate statement) using the = operator. This process is called copy assignment (or just assignment) for short.

Copy assignment is named such because it copies the value on the right-hand side of the = operator to the variable on the left-hand side of the operator. The = operator is called the assignment operator.

Here’s an example where we use assignment twice:

When we assign value 7 to variable width, the value 5 that was there previously is overwritten. Normal variables can only hold one value at a time.

Warning

One of the most common mistakes that new programmers make is to confuse the assignment operator (=) with the equality operator (==). Assignment (=) is used to assign a value to a variable. Equality (==) is used to test whether two operands are equal in value.

Copy and direct initialization

One downside of assignment is that it requires at least two statements: one to define the variable, and one to assign the value.

These two steps can be combined. When a variable is defined, you can also provide an initial value for the variable at the same time. This is called initialization.

C++ supports three basic ways to initialize a variable. First, we can do copy initialization by using an equals sign:

Much like copy assignment, this copies the value on the right-hand side of the equals to the variable being created on the left-hand side.

Second, we can do direct initialization by using parenthesis.

For simple data types (like integers), copy and direct initialization are essentially the same. But for some advanced types, direct initialization can perform better than copy initialization. Prior to C++11, direct initialization was recommended over copy initialization in most cases because of the performance boost.

Brace initialization

Unfortunately, parenthesis-based direct initialization can’t be used for all types of initialization (such as initializing an object with a list of data). In an attempt to provide a more consistent initialization mechanism, C++11 added a new syntax called brace initialization (also sometimes called uniform initialization) that uses curly braces.

Brace initialization comes in two forms:

These two forms function almost identically, but the direct form is generally preferred.

Initializing a variable with empty braces indicates zero initialization. Zero initialization generally initializes the variable to zero (or empty, if that’s more appropriate for a given type).

Brace initialization has the added benefit of disallowing “narrowing” conversions. This means that if you try to use brace initialization to initialize a variable with a value it can not safely hold, the compiler will throw a warning or an error. For example:

In the above snippet, we’re trying to assign a number (4.5) that has a fractional part (the .5 part) to an integer variable (which can only hold numbers without fractional parts). Copy and direct initialization would drop the fractional part, resulting in initialization of value 4 into variable width. However, with brace initialization, this will cause the compiler to issue an error (which is generally a good thing, because losing data is rarely desired). Conversions that can be done without potential data loss are allowed.

Best practice

Favor direct brace initialization whenever possible.

Author's note

Many examples in this tutorial series were written before brace initialization existed and thus still use copy or direct initialization. We’re working on getting these updated. Please forgive our lack of adherence to best practices in this regard.

Q: C++ provides copy, direct, and brace initialization, and copy assignment. Is there a direct or brace assignment?

No, C++ does not support a direct or brace assignment syntax.

In C++11, move assignment was added, but it uses the same syntax as copy assignment. We cover move assignment in the chapter on smart pointers.

Q: When should I initialize with { 0 } vs {}?

Use an explicit initialization value if you’re actually using that value.

Use zero initialization if the value is temporary and will be replaced.

Initialize your variables

Initialize your variables upon creation. You may eventually find cases where you want to ignore this advice for a specific reason (e.g. a performance critical section of code that uses a lot of variables), and that’s okay, as long the choice is made deliberately.

For more discussion on this topic, Bjarne Stroustrup (creator of C++) and Herb Sutter (C++ expert) make this recommendation themselves here.

We explore what happens if you try to use a variable that doesn’t have a well-defined value in lesson 1.6 -- Uninitialized variables and undefined behavior.

Best practice

Initialize your variables upon creation.

Initializing multiple variables

In the last section, we noted that it is possible to define multiple variables of the same type in a single statement by separating the names with a comma:

We also noted that best practice is to avoid this syntax altogether. However, since you may encounter other code that uses this style, it’s still useful to talk a little bit more about it, if for no other reason than to reinforce some of the reasons you should be avoiding it.

You can initialize multiple variables defined on the same line:

Unfortunately, there’s a common pitfall here that can occur when the programmer mistakenly tries to initialize both variables by using one initialization statement:

In the top statement, variable “a” will be left uninitialized, and the compiler may or may not complain. If it doesn’t, this is a great way to have your program intermittently crash and produce sporadic results. We’ll talk more about what happens if you use uninitialized variables shortly.

The best way to remember that this is wrong is to consider the case of direct initialization or brace initialization:

This makes it seem a little more clear that the value 5 is only being used to initialize variable b or d, not a or c.

Quiz time

Question #1

What is the difference between initialization and assignment?

Show Solution

Question #2

What form of initialization should you be using (assume your compiler is C++11 compliant)?

Show Solution


1.5 -- Introduction to iostream: cout, cin, and endl
Index
1.3 -- Introduction to variables

131 comments to 1.4 — Variable assignment and initialization

  • Quiz :What is the difference between initialization and assignment?
    Difference is where an Initialization gives a variable an initial value at the point when it is created in your coding .
    While an assignment gives a variable a value at some point after the variable is created later in your coding process.

    What form of initialization should you be using (assume your compiler is C++11 compliant)?
    I would use direct brace initialization since it is safe.

  • Yash

    good article and example why brace intilization is safe https://stackoverflow.com/questions/18222926/why-is-list-initialization-using-curly-braces-better-than-the-alternatives

  • Ahmed Sersawy

    thanks for this great tutorial

  • Dragonlynx

    Hello, so i dont get really the diffrence between () and {} when giving a variable a number, since to me it seems like it does the same, also why is there spaces between the numbers if to my understanding, spaces set it to 0? what does copy inisilation (i really cant spell it sorry) even mean? i know i have alot of questions, but im 11 so please dont be too harsh on me, but i really dont get the diffrence between most of the stuff, but ill still do as the tutorial says.

    • broccoli_fan

      Hey! Direct initialization, the one with the parentheses (), does not work for lists data types (they store multiple values of the same data type into one variable), so we use brace initialization, with the curly brackets {}, for that. I am pretty sure that the person who wrote this blog, Alex, put spaces when initializing a value using brace or direct initialization so that we could see what value he was initializing instead of seeing it all jumbled up as {3}, for example. (That was what you were asking about, right? Also, the spaces will only set the value of the variable to be 0 when there is no value, such as an integer, in between the braces or parentheses.) Copy initialization is just another way to initialize a variable. It uses the same principles as the other initialization techniques, but it just doesn't work for some advanced data types. That is why Alex told us to, in most cases, use direct brace initialization (it works when plain direct initialization doesn't, and it works better than copy initialization). If you are asking why it is called copy initialization, I am not too sure, but I doubt that it is very important. If you have any other questions, just ask, I hope this helps!

    • Dragonlynx

      Thank you so much!!! It really helped :D i understand it alot better now!

  • Chayim

    What does it mean "initializing an object ---with a list of data---" ?

  • jojo

    How do you know when to use each initialization method?

    • nascardriver

      Always use list/brace/uniform initialization

      You know that you need something else when this stops working.

  • Jay

    What are other advantages of using direct brace initialization over copy initialization? Will it give any performance advantage?

  • George

    Is there any difference between the following two ways of assigning a value to x?

    • nascardriver

      The second is not initialization. Reading from `x` causes undefined behavior.
      Initializing variables comes with a performance cost, but prevents uninitialized variables. You should only not initialize variables if you're sure about what you're doing. Do you know if `std::cin` reads from `x`? Do you know what happens to `x` if `std::cin` fails to extract a value? You probably don't know (It doesn't read. It sets `x` to 0.), so it's better to initialize `x`.

  • direct initialization

    Is "direct initialization" for variables the same as "copy constructor" for objects of classes?

    • nascardriver

      No, direct initialization is a form of initialization, whereas a copy constructor is a special function. They're unrelated.

  • Jim Guth

    This may seem like a dumb question, but why doesn't int main () use {} instead?  I understand main is a function.  Since we haven't covered functions yet do they require brackets too?

    • Gabe

      No, the () after a function name are used in order to take in arguments (input) to use for part of that function; however, the {} are used as part of that function's BODY where the statements are declared in. {} have different meanings where for variables, it gives it an initial value, but for functions, it represents the body of a function.

      Nascardriver or anyone, please correct me if I am wrong or not.

  • KapyoniK

    Hello,

    I'm very thankfull for your tutorials so first of all thanks !

    Even though I understand clearly why the braces initialization is prefered, i still find it looks ugly compared to normal initialization.

    I'm talking specifically about "looks". I'm fluent in Java, and used to be in C, but here I'm pretty confused, because I'm seeing in my mind how a source code would look like with all those braces everywhere and it hurts...

    Thanks anyways, any ideas about this ? :)

    • i am totally agree with you, it looks like a array wit the {} that is confusing me a little

      anyways as well very happy with this tutorials

      kind regards ,
      @Okido1

    • Paulo Filipe

      Typical Java programmer mindset.

      We're so used to the java's simple declaration and initialization:

      that it's hard to look at other options.

      But, this is not java, and you really have to drop this "ugliness" mindset and open your mind to something new.
      C++ is very different from java. It is a lot more powerful, and goes deeper in certain concepts that java handles itself and hides from the programmer, so you should consider adopting all best practices of this beautiful language.

      My story: I started with c++ first and when I learned java I was like: "Dude, it looks so wrong to use an equals sign to initialize variables! I am ruining the program's performance this way!!"
      But the habits made me just accept that in java we use the = everywhere.

      I am back to these c++ classes because I miss the complexity that java does't provide.

      Regards!!

    • BeanSprugget

      I've never really programmed before, but I do agree that brace initialization seems "uglier" and less familiar. I think though, that it is probably helpful for differentiating "=" as assignment and "==" as comparison; copy initialization doesn't match our intuitions from learning maths in school.

  • overpriced

    on repl.it(i use that as an IDE because my pc cant handle anything else lol), you cant give an int a value in another line(e.g. i do this)

    i cannot do that for any sort of reason, but if i do this

    it works. was that deprecated or is it an issue with repl.it?

    • nascardriver

      That's legal. It works for me with default settings on repl.it.
      You shouldn't do it. If you can initialize a variable, initialize it with list initialization.

  • Jimmy Hunter

    Maybe a typo?  Been awhile since I took English in High school.  The definite article rule back then in Alabama was, in general, use "a" if the word following it begins with a consonant and use "an" if the word following it begins with a vowel.  One exception to that was words beginning with h where the h is silent: write "...for an hour", not "...for a hour" and "...it would be an honor..." instead of "...it would be a honor..".

    Typo = "the compiler will throw an warning or an error."
    Correct = "the compiler will throw a warning or an error.

    I think?

  • Jonathan Tairov

    int c;
    c = 2;

    when I type this in to Visual Studio 2019, this gives me an error and i don't know why. The second statement is where the error shows up, but if i did this on one line, (int c = 2;), I don;t get an error. Help?

    • nascardriver

      You probably get a warning, because you're not initializing a variable that you could have initialized. If you can initialize a variable, do so.

    • In the case of primitive types this:

      and this:

      have the same result, right?
      but in the case of objects they can be difference because initialization calls the copy constructor, and later assignments call the operator=, am I right?

  • If brace initialization is the way to go why i get "warning: extended initializer lists only available with -std=c++11 or -std=gnu++11" when trying to use int a{};

    Nevermind, just used --std=2a

  • Prince

    #include <iostream>

    int main()
    {
        std::cout << "Enter your name: ";
        char name[0];
        std::cin >> name;
        std::cout << name << " your dreams will come true";

        return 0;
    }

    1>------ Build started: Project: Project2, Configuration: Debug Win32 ------
    1>Project2.cpp
    1>C:\Users\tomas\source\repos\Project2\Project2\Project2.cpp(6,7): error C2466: cannot allocate an array of constant size 0
    1>C:\Users\tomas\source\repos\Project2\Project2\Project2.cpp(6,14): error C2133: 'name': unknown size
    1>Done building project "Project2.vcxproj" -- FAILED.
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

    • Lifthra

      I'm not an expert but char is used only to indicate letters ( like char letterA = a; ).
      You should be using string, that is used to indicate words or phrases.

      • DoITCreative

        He is using char array, which is c-type string.
        char[] initialization requires size, but Prince used 0 as string size, which is incorrect.

        This will work, but never make it like so, because if user will enter string, which has > then 50 chars, then he will override the stack, which is quite nasty bug, see buffer overflow exploits to learn about it:

        Better to use std::string to store strings:

  • Joshua

    When I tried to test the variable assigning, it says I have the error "cannot open source file iostream" how do I fix this?

  • Cuyler Brehaut

    Hey, you said there wasn't such a thing as "brace assignment", but I wrote:

    and it compiled fine and ran fine.
    What is this actually doing, if it isn't "brace assignment"?

    • nascardriver

      Hi!

      What you did works with scalar types and is similar to brace initialization. It disallows narrowing casts like this:

      But for class-types, which we'll talk about later, the two assignments do different things.

  • Marcin Rutkowski

    Hi  ...impressive course :)
    I'm far from a pro but I program c++ for last 6 months as a hobby :)

    Question  ...what is the consequence is we initialize variables by "not preferred way"   ...as a beginner for me is important if "something" is working correctly and my code does not have to be "pretty"   and if I get used to one style I need good reason to change it so when we talking about performance boost what it means and what would be a difference between initializing 10M integers correct way between initializing 10M integers "not preferred way". Is it significant ?? or this is an agreement between pros as a best practice to easier read someone else code ??

    • nascardriver

      There's no different in performance if you're using a somewhat recent version of C++. The difference is in versatility and safety. Brace initialization can be used almost everywhere, can zero-initialize, and doesn't allow narrowing casts.

  • mark

    Can you help with this issue?

    Using Visual Studio Code on Mac OS Catalina. I tried the final exercise of this chapter.

    VSCode flagged errors upon initialization of variables. I used both clang++ and g++ as compilers. I tried compiling anyway, and this was the result:

    Removal of the squiggly brackets, or introduction of parentheses with a 0 declaration (for example, a "(0)") allows compiling.

    Any ideas?

Leave a Comment

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