Core Syntax
Core Syntax
Variables, types, operators, expressions, and declarations at a glance.
Core Syntax
Variables, types, operators, expressions, and declarations at a glance.
#include <iostream>
int main() {
std::cout << "Hello, C++\n";
return 0;
}
boolchar, wchar_t, char8_t, char16_t, char32_tshort, int, long, long longfloat, double, long doublevoidint a = 1; // copy initialization
int b(2); // direct initialization
int c{3}; // brace initialization
const int d = 4; // immutable
constexpr int e = 5; // compile-time constant
auto name = std::string{"Ada"};
int value = 10;
int& ref = value; // lvalue reference
const int& cref = value; // read-only reference
int&& rref = 42; // rvalue reference
+ - * / %== != < <= > >=&& || !& | ^ ~ << >>= += -= *= /= %=., ->, ::condition ? a : bint total = price * count;
bool ready = total > 0 && connected;
auto label = ready ? "ok" : "pending";
These are not just symbols to memorize. They are the core vocabulary for state updates, branching, and object access.
double x = 3.9;
int i = static_cast<int>(x);
Base* base = dynamic_cast<Base*>(ptr);
const char* raw = reinterpret_cast<const char*>(buffer);
static_cast: normal explicit conversionsdynamic_cast: safe downcasts in polymorphic hierarchiesconst_cast: add or remove constness only when the underlying object really permits itreinterpret_cast: last-resort low-level bit reinterpretationPrefer the narrowest cast that expresses the intended boundary.
namespace math {
int square(int x) { return x * x; }
}
using Index = std::size_t;
namespace fs = std::filesystem;
Aliases help when a type or namespace is verbose, but keep them local enough that readers can still tell what they refer to.
auto when the type is obvious from the initializer.const by default.constexpr for values known at compile time.auto, decltype, and deductionstd::vector<int> values{1, 2, 3};
auto it = values.begin(); // iterator type deduced
decltype(values.size()) count = values.size();
auto follows the initializer and usually drops top-level const.auto& keeps reference semantics.decltype(expr) asks the compiler for the exact type of an expression.const int value = 42;
auto copy = value; // int
auto& ref = value; // const int&
This is one of the first deduction rules worth remembering because it affects mutation and copying.
[[nodiscard]] int parse(std::string_view text);
constinit inline int global_counter = 0;
consteval int version() {
return 23;
}
[[nodiscard]] catches ignored results that probably matter.constinit guarantees static initialization without forcing constness.consteval requires evaluation at compile time.struct Point {
int x{};
int y{};
auto operator<=>(const Point&) const = default;
};
Point p{.x = 3, .y = 4};
<=> can generate all comparison operators.const, volatile, mutableUnderstanding those terms makes later topics such as templates, move semantics, and linkage errors much easier to reason about.
#include <vector>
#include "widget.hpp"
const and constexpr when a value should not changeint main() {
int count{3};
if (count > 0) {
return count;
}
return 0;
}
Refactor the example into a named helper with a single responsibility. If the logic gets easier to test, the design probably improved.
bool is_even(int value) {
return value % 2 == 0;
}
int main() {
return is_even(4) ? 0 : 1;
}