

新闻资讯
技术学院字面量类型由后缀和上下文共同决定:整数如123默认为int(若可容纳),123ULL强制为unsigned long long;浮点如1.0为double、1.0f为float;字符串字面量类型是const char[N],非std::string;UDL后缀须以下划线开头且函数需constexpr;nullptr类型为std::nullptr_t。
不加修饰的数字字面量,比如 123、3.14,类型不是“默认 int”或“默认 double”——C++ 标准只规定了最小保证范围,具体类型取决于字面量形式和编译器实现。例如:123 是 int(如果 int 能容纳),但 1234567890123 在 32 位系统上就可能是 long long;123U 明确是 unsigned int,而 123ULL 强制为 unsigned long long。
浮点字面量同理:1.0 是 double,1.0f 是 float,1.0L 是 long double。漏写 f 可能在 float 比较中引发隐式转换和精度丢失,比如 float x = 0.1; 实际存储的是近似值,而 0.1f == 0.1 为 false(后者是 double)。
写 "hello" 得到的是一个以 \0 结尾的字符数组,类型为 const char[6](含终止符)。它不能直接赋给 std::string 变量而不触发构造(虽然语法允许,那是调用了隐式构造函数),更不能赋给 char*(C++11 起禁止非 const 转换)。
const char* p = "hello"; ✅ 合法char* p = "hello"; ❌ 编译错误(弃用的转换)std::string s = "hello"; ✅ 调用 std::string(const char*) 构造auto s = "hello"; → s 类型是 const char[6],不是 std::string
多行字符串必须用反斜杠续行或用原始字符串字面量:R"(line1\nline2)",否则 "line1\nline2" 中的换行会破坏语法。
定义像 123_km 这样的字面量,本质是调用一个带特定后缀名的 constexpr 函数。它必须满足:参数类型只能是 unsigned long long、long double、const char*、char、w 等有限几种,且函数必须是
char_tconstexpr 才能用于常量表达式。
constexpr long long operator"" _km(unsigned long long val) {
return static_cast(val * 1000);
}
// 使用
constexpr auto d = 5_km; // ✅ 编译期计算
int x = 5_km; // ✅ 运行时也行,但失去 constexpr 优势
常见陷阱:
_km),否则编译失败constexpr 上下文operator"" _s(const char*, size_t))参数是裸指针 + 长度,不带终止符,别直接当 C 字符串用true 和 false 类型固定为 bool,不会退化成整数;nullptr 类型是 std::nullptr_t,专用于指针比较,比 NULL(常定义为 0 或 ((void*)0))更安全。
但在模板函数中,nullptr 的类型推导可能出人意料:
templatevoid f(T) { } f(nullptr); // T 推导为 std::nullptr_t,不是 void* f(0); // T 推导为 int
所以重载函数里区分指针和整数时,void f(std::nullptr_t) 比 void f(void*) 更精准;而用 auto 推导时,auto p = nullptr; 得到的是 std::nullptr_t,不是指针类型,不能解引用。
字面量看着简单,但类型细节一旦错位,轻则隐式转换带来性能损耗,重则模板匹配失败或 constexpr 场景编译不过。最易被忽略的是字符串字面量的数组类型本质,以及 UDL 后缀命名规则和 constexpr 约束。