未特化std::numeric_limits的类型会有什么行为?
关于
std::numeric_limits与自定义类型的疑问 测试代码与初始输出
#include <limits> #include <iostream> struct Foo { int x; }; static_assert(!std::numeric_limits<Foo>::is_specialized); int main() { std::cout << "---" << std::endl; std::cout << std::numeric_limits<Foo>::lowest().x << std::endl; std::cout << std::numeric_limits<Foo>::min().x << std::endl; std::cout << std::numeric_limits<Foo>::max().x << std::endl; std::cout << "---" << std::endl; }
运行后输出:
--- 0 0 0 ---
疑问点
- 输出的三个
0数值来自何处? - 根据C++标准说明,
std::numeric_limits仅为算术类型提供特化,自定义类型Foo未特化就使用该模板是否属于未定义行为? - 若将
Foo中的int改为char,输出变为:
--- ---
为何原本的中间输出行(含std::endl)消失了?
解答
1. 数值0的来源
未特化的std::numeric_limits<T>模板中,lowest()、min()、max()这些成员函数默认返回值初始化的T对象。对于自定义结构体Foo,值初始化会将其成员x零初始化,因此最终输出的是0。
2. 是否属于未定义行为?
是的。C++标准明确规定,std::numeric_limits的成员函数(除is_specialized外)仅对已特化的类型(即算术类型,以及标准库明确特化的其他类型)保证行为合法。对于未特化的自定义类型,调用这些成员函数属于未定义行为——虽然部分编译器会提供默认实现,但这并非标准强制要求,更换编译器或环境可能出现完全不同的结果。
3. char版本输出异常的原因
当Foo的成员改为char时,std::numeric_limits<Foo>::lowest().x返回的是值初始化的char(即'\0',空字符)。std::cout输出空字符时不会产生可见内容,后续的std::endl虽会刷新缓冲区,但前面的空字符无输出,导致中间三行(空字符+换行)没有可见效果,看起来像是输出消失了。实际上代码执行了所有输出操作,只是空字符在终端中不可见。
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

