# Types, Variables, const and auto — C++

Source: https://www.skillbyai.com/en/cpp/f-basics

> Use fundamental types, initialisation, const and auto correctly.

## The building blocks

C++ has **fundamental types**: `bool`, `char`, integers (`short`, `int`, `long`, `long long`, with `unsigned` variants), floating point (`float`, `double`) and `void`. Sizes are platform-dependent within limits; use **fixed-width** types from `<cstdint>` (`std::int32_t`, `std::uint64_t`) when exact sizes matter. Prefer **brace initialisation** (`int count{0};`), which **prevents narrowing** conversions such as silently turning a `double` into an `int`. **Uninitialised local variables** hold indeterminate values, and reading them is undefined behaviour, so always initialise. **`const`** marks values that must not change; **`constexpr`** marks values (and functions) that can be computed at **compile time**. **`auto`** deduces a variable's type from its initialiser, reducing noise for long type names such as iterators, while keeping static typing. Use **`std::string`** for text, not C-style `char` arrays. Integer **overflow** of signed types is undefined behaviour, a common source of bugs in competitive programming; use `long long` when values can exceed about 2.1 billion.

## Initialisation, const, constexpr and auto

Brace initialisation rejects narrowing at compile time.

```cpp
#include <cstdint>
#include <string>
#include <vector>

int main() {
    int count{0};                    // always initialise
    double price{499.5};
    // int rounded{price};           // error: narrowing conversion rejected by braces
    int rounded = static_cast<int>(price);   // explicit, visible conversion

    const std::string shop{"GeekMart"};      // cannot be modified
    constexpr int maxItems = 100;            // compile-time constant
    std::int64_t bigTotal = 3'000'000'000;   // digit separators (C++14)

    std::vector<std::string> names{"Asha", "Ravi"};
    auto first = names.front();              // std::string (a copy)
    auto& firstRef = names.front();          // reference, no copy
    auto it = names.begin();                 // std::vector<std::string>::iterator
    return 0;
}
```

## auto drops references and const

`auto x = v.front();` makes a copy. Write `auto&` or `const auto&` when you want a reference, especially in range-based for loops over containers of large objects.

**Quiz:** What does brace initialisation such as `int x{3.7};` do?

- [ ] Silently truncates to 3
- [ ] Rounds to 4
- [x] Fails to compile because it is a narrowing conversion
- [ ] Creates a double

*Answer:* Fails to compile because it is a narrowing conversion. List initialisation forbids narrowing conversions, catching accidental data loss.
