1.3 Variables

Like in Rust, creating a variable requires two steps, declaration and initialization.

The traditional syntax for declaration and initialization is <type> <var name> = <value>;, and these two steps can be separated:

int a = 5;
char b;
b = 'A';

The above syntax is compatible with C, which has a problem: if you initialize an int with a float:

int a = 5.5;
assert(a == 5);

The value will be implicitly converted (recent compilers will give a warning when this happens; see Figure 1.1). C++11 introduced the “uniform initialization” syntax, which forbids this implicit conversion. In its simplest form:

int a{5};
When implicit conversion occurs, a decent modern C++ compiler will give a warning.

Figure 1.1: When implicit conversion occurs, a decent modern C++ compiler will give a warning.

If you try int a{5.5}; with this syntax, the compiler will give an error and abort (Figure 1.2 ). In addition, you can’t separate the two parts:

// not allowed
int a;
a{5}
The uniform initialization syntax.

Figure 1.2: The uniform initialization syntax.

Of course, the uniform initialization syntax isn’t invented just to prevent implicit conversion. As you’ll see later, it can become handy when initializing complicated, non-primitive data types.

1.3.1 Mutability

Variables are mutable by default. If you want to create an immutable variable, use the const keyword.

// Rust
let a = 5;
let mut b = 10;

is equivalent to

//C++
const auto a = 5;
auto b = 10;

If const is used to create an immutable variable, how to create a real “constant” that’s evaluated at compile time? The answer is consexpr.

// Rust
const LIGHT_SPEED: f64 = 2.99792458e8;

is equivalent to

constexpr double LIGHT_SPEED = 2.99792458e8;

What about constant strings? Well, like Rust, you can’t use the dynamically allocated std::string.

// Rust
const NAME: String = "Hideyo".to_string(); // not allowed!
const NAME: &'static str = "Hideyo";       // good
//C++
constexpr std::string NAME = "Hideyo"; // not allowed!
constexpr char NAME[] = "Hideyo";      // good

So you have to use an array of characters. Well, it’s technically closer to const NAME: &[u8] = b"Hideyo";. Then, if you need to use the std::string, you need explicit conversion:

#include <iostream>

constexpr char NAME[] = "Hideyo";
constexpr char NAME_UTF8[] = "英世";

int main()
{
    const std::string NAME_STRING(NAME);
    const std::string NAME_UTF8_STRING(NAME_UTF8);
    // thank god UTF8 works! If you were in C you would have a hard time.
    std::cout << NAME_UTF8_STRING << " " << NAME_STRING << std::endl;
}