c++变量定义必须显式声明类型,不可省略;推荐用{}统一初始化以禁用窄化转换;const为运行期常量,constexpr为编译期常量;局部static变量首次调用时线程安全初始化。

变量定义必须声明类型,不能省略
C++ 不像 Python 或 JavaScript,所有变量在定义时就得说清楚是什么类型。漏写类型不是语法警告,而是直接编译失败。
-
int x = 42;合法;x = 42;在函数外或未声明前使用会报error: 'x' was not declared in this scope - 常见误写:
var x = 42;(这是 JS 写法,C++ 里var不是关键字)、auto x = 42;虽然合法,但仅限于有初始化值的场景,且类型由右值推导,不等于“无类型” - 内置类型别名如
size_t、ptrdiff_t要加std::前缀或用using引入,不能当基础类型直接用
初始化方式不止等号一种,统一初始化更安全
用 =、()、{} 都能初始化,但行为不同——尤其对类类型和窄化转换(narrowing conversion)。
-
int a = 3.14;编译通过,但静默截断为3;int b{3.14};直接报错:error: narrowing conversion of '3.1400000000000001e+0' from 'double' to 'int' inside { } - 推荐优先用
{}(统一初始化),它禁用隐式窄化,也避免“最令人烦恼的解析”(most vexing parse)问题,比如vector<int> v();</int>是函数声明,不是变量定义;而vector<int> v{};</int>明确是默认构造 - 对于 POD 类型(如
struct Point { int x, y; };),Point p{};会零初始化成员,Point p;则不初始化(值不确定)
const 和 constexpr 的初始化时机和约束完全不同
两者都表示“不可变”,但 const 是运行期常量,constexpr 是编译期常量——这直接影响能否用作数组长度、模板参数等。
-
const int n = rand();合法(运行期赋值),但int arr[n];在标准 C++ 中仍是 VLA(非标准扩展),多数编译器不支持 -
constexpr int m = 42;合法,int arr[m];可以;但constexpr int k = std::time(nullptr);报错:调用非constexpr函数 - 类内
static constexpr成员可直接初始化(如static constexpr double PI = 3.14159;),无需类外定义;普通static const成员仍需类外定义(除非是整型且已初始化)
局部静态变量只初始化一次,但要注意线程安全
函数内部的 static 变量会在第一次执行到定义语句时初始化,之后调用跳过初始化——这个特性常被用来实现单例或延迟初始化缓存。
立即学习“C++免费学习笔记(深入)”;
-
static std::map<:string int> cache;</:string>第一次调用函数时构造空 map,后续复用 - C++11 起,这种初始化是线程安全的(编译器自动加锁),但前提是初始化表达式本身不抛异常;若抛出,该线程终止,其他线程阻塞等待,再次进入时重试
- 陷阱:
static T x = f();中f()若依赖全局状态或外部输入,可能引发初始化顺序问题(尤其是跨编译单元)
{} 和 = 的差别,可能决定程序是否编译、是否线程安全、是否零初始化。这些不是风格选择,是语言机制强制的行为差异。











