Variables, Types & Type Inference (auto)
ভ্যারিয়েবল, টাইপ ও auto
1. C++ Is Statically Typed
Every variable has a type known at compile time. The type determines its size, what
operations are allowed, and how the bits are interpreted. Unlike Python, you cannot reassign an int
variable to hold a string later.
int variable পরে আর string-এ পরিবর্তন করা যাবে না।
2. Built-in Primitive Types
| Type | Typical size | Use for |
|---|---|---|
bool | 1 byte | true / false |
char | 1 byte | Single character |
short | 2 bytes | Small integers |
int | 4 bytes | General integers (default choice) |
long long | 8 bytes | Large integers |
float | 4 bytes | Less precise reals |
double | 8 bytes | Default real (use this) |
3. Declaration & Initialization
#include <iostream>
int main() {
int a = 5; // copy initialization
int b(5); // direct initialization
int c{5}; // uniform (brace) initialization — C++11+
int d = {5}; // copy-list initialization
std::cout << a << " " << b << " " << c << " " << d << "\n";
// Brace init catches narrowing!
// int e{3.14}; // ERROR: narrowing conversion
return 0;
}
{} when possible — it catches dangerous narrowing conversions at compile time.
4. auto — Type Inference
Since C++11, you can use auto to let the compiler deduce the type from the initializer.
The variable still has a strict static type — auto just saves typing.
#include <iostream>
#include <vector>
#include <string>
int main() {
auto i = 42; // int
auto d = 3.14; // double
auto s = std::string{"hi"}; // std::string
auto v = std::vector<int>{1,2,3}; // std::vector<int>
std::cout << i << " " << d << " " << s << " size=" << v.size() << "\n";
}
auto drops const and reference by default. Use const auto& when you want a non-copying view.
5. const and constexpr
const means: cannot change after initialization. constexpr means: must be a
compile-time constant. Use them aggressively — the compiler optimizes harder when it knows things can't change.
#include <iostream>
int main() {
const int max_users = 100;
constexpr double PI = 3.14159265358979;
// max_users = 200; // ERROR: read-only
std::cout << "Max = " << max_users << ", PI = " << PI << "\n";
}
6. Type Conversion
Implicit conversions can hide bugs. Use explicit casts:
#include <iostream>
int main() {
int a = 7, b = 2;
std::cout << a / b << "\n"; // 3 (integer division)
std::cout << static_cast<double>(a) / b << "\n"; // 3.5
}
C++ has four named casts:
static_cast<T>(x)— safe compile-time conversionconst_cast<T>(x)— stripconst(rare)reinterpret_cast<T>(x)— bit-level reinterpretation (dangerous)dynamic_cast<T>(x)— safe downcast in inheritance hierarchies
7. Practice Problems
- Declare three variables with brace initialization: an int 7, a double 2.5, a string "C++".
✨ Show Answer
int a{7}; double d{2.5}; std::string s{"C++"}; - Why does
int x{3.14};fail to compile?✨ Show Answer
Brace init disallows narrowing conversions. Converting double 3.14 to int loses precision (would store 3). Use
int x = 3.14;if you really want truncation, orint x{static_cast<int>(3.14)};. - Use
autoto declare a variable holding the result of1 + 2.5. What's its type?✨ Show Answer
auto x = 1 + 2.5;—xhas typedoublebecause1is promoted todoublebefore adding. - What's the difference between
const intandconstexpr int?✨ Show Answer
const: value can't be modified, but it could be set at runtime.constexpr: value must be known at compile time. Everyconstexpris alsoconst, but not vice versa. - Predict the output:
std::cout << 7/2 << " " << 7/2.0;✨ Show Answer
3 3.5. Integer division truncates; mixing int with double promotes to double division. - Why prefer
const auto&overautoin a range-for?✨ Show Answer
autocopies each element. For large objects (strings, vectors), copying is wasteful.const auto&binds a read-only reference — no copy, plus the compiler enforces you don't accidentally modify the element. - Convert
double pi = 3.14;to int safely.✨ Show Answer
int p = static_cast<int>(pi);— explicit, searchable, intentional. Avoid C-style(int)pi. - Write a constexpr function that returns the square of an integer.
✨ Show Answer
constexpr int square(int x) { return x * x; } // constexpr int s = square(7); // computed at compile time → 49 - What does
uint32_tmean?✨ Show Answer
An unsigned integer with exactly 32 bits, defined in
<cstdint>. Range: 0 to 4,294,967,295. Use it when exact size matters (file formats, network protocols). - Demonstrate that
booltakes 1 byte despite being conceptually 1 bit.✨ Show Answer
boolsize.cpp#include <iostream> int main() { std::cout << sizeof(bool) << "\n"; // 1 }Memory is byte-addressable; CPUs can't address single bits.
std::vector<bool>is the rare exception that packs bits.
Summary
C++ is statically typed — every variable has a compile-time type. Use brace init {}
to catch narrowing. Use auto when the type is obvious from the initializer; use const auto&
in loops to avoid copies. const means immutable; constexpr means compile-time-known.