C++窄化转换需求差异疑问:函数与构造器调用为何不同?
void func(float f) { } struct Foo { Foo(float b) {} }; int main() { short b = 1; func(b);/* WORKS FINE*/ Foo foo{ b }; /*REQUIRES NARROWING CONVERSION FROM SHORT TO FLOAT */ Foo foo2{ (short)b }; /*REQUIRES NARROWING CONVERSION FROM SHORT TO FLOAT */ Foo foo3{ (short)7 }; /* WORKS FINE */ }
问题解答
第一个问题:为何short左值能调用参数为float的func,却无法用于Foo的列表初始化?
C++函数调用的参数匹配允许常规隐式转换,short到float的数值转换属于合法范畴,编译器会自动完成转换,这是函数参数传递的默认规则,没有额外限制。
但花括号形式的列表初始化规则要严格得多:它明确禁止「窄化转换」。这里的判定逻辑是:如果转换的源是非常量表达式(比如运行时才能确定值的变量b),哪怕short的所有理论值都能被float精确表示,编译器也会因为无法在编译期确认变量的具体值是否能无损转换,直接判定这是窄化转换并抛出错误。
第二个问题:为何传递右值short不会触发窄化转换报错?
核心区别在于这个右值是否是编译期常量表达式:
(short)7是编译期就能确定值的常量表达式,编译器可以明确验证7能被float精确表示,完全符合列表初始化的转换规则,因此不属于窄化转换,不会报错。- 而
(short)b虽然是强制转换后的右值,但b是变量,属于非常量表达式,编译器无法在编译期确定它的具体值,所以依然会被判定为窄化转换,触发报错。
内容的提问来源于stack exchange,提问作者Zebrafish
相关产品推荐
相关产品推荐

