面试题答案
一键面试编译期常量表达式规则
- 基本类型常量:整型、枚举、指针和引用等类型的常量表达式。例如
const int a = 5;
这里a
是编译期常量表达式,可用于函数模板非类型参数。 - 字面值常量:如整数
5
、浮点数3.14
、字符串字面值"hello"
等是编译期常量表达式。但字符串字面值在作为非类型参数时有限制,仅能是const char*
且指向静态存储区。 - 算术运算:由编译期常量表达式参与的算术运算结果仍是编译期常量表达式。如
const int b = 3 + 2;
- 条件运算符:
const int c = (a > 10)? 20 : 30;
若a
是编译期常量表达式,此整个表达式也是编译期常量表达式。 - sizeof 运算符:
sizeof
操作数是编译期常量表达式,结果也是编译期常量表达式。例如const int size = sizeof(int);
对非类型参数取值范围的影响
- 整型非类型参数:只能接受编译期可确定的整数值,限制了其取值必须在编译时就能计算得出,不能是运行时才确定的值。比如不能使用运行时输入的值作为非类型参数。
- 指针和引用非类型参数:必须指向或引用具有静态存储期的对象,不能是局部变量等具有自动存储期的对象。这限制了可作为此类非类型参数的对象范围。
模板实例化中编译器对非类型参数取值的处理
- 检查合法性:编译器在模板实例化时,会检查非类型参数是否符合编译期常量表达式规则。若符合,则进行实例化。
- 替换与生成代码:将模板中的非类型参数用具体值替换,生成相应的代码。例如对于模板
template <int N> void func() { /* code */ }
,实例化func<5>()
时,编译器将N
替换为5
并生成对应代码。
取值超出预期范围时的错误提示及调试
- 错误提示:编译器通常会给出类似 “template argument for non - type parameter is not a constant expression” 等提示,指出非类型参数不是编译期常量表达式。
- 调试方法:
- 检查参数定义:确认非类型参数是否按编译期常量表达式规则定义,如是否使用了运行时才确定的变量。
- 检查表达式计算:若参数是表达式,检查表达式中所有操作数和运算是否都满足编译期常量表达式要求,例如是否存在非法的函数调用等。
- 确认存储期:对于指针和引用非类型参数,确认指向或引用的对象是否具有合适的存储期。