为何同类型const CC&:局部变量可赋值字符串字面量,函数传参却编译失败?
问题描述
在以下C++代码中,main()函数内的局部变量rcc与foo()函数的参数r类型均为const CC&,但局部变量可以成功赋值字符串字面量,向foo()传递字符串字面量时却编译失败,为何同类型会出现不同行为?编译环境为Visual Studio 2019。
代码示例:
typedef char CC[5]; void foo(const CC& r) { std::cout << r << std::endl; } void bar(const char(&r)[]) { std::cout << r << std::endl; } int main() { const CC &rcc = "ex"; // 所有标准下均编译通过 const char(&rchar)[] = "ex"; // 所有标准下均编译通过 std::cout << rcc << ' ' << rchar << std::endl; bar("ex"); // 仅ISO C++20标准下编译通过 foo("ex"); // 所有标准下均编译失败 return 0; }
编译错误信息:
error C2664: 'void foo(const CC (&))': cannot convert argument 1 from 'const char [3]' to 'const CC (&)' message : Reason: cannot convert from 'const char [3]' to 'const CC' message : There is no context in which this conversion is possible message : see declaration of 'foo'
原因分析
typedef char CC[5]的类型本质:CC是长度为5的char数组的别名,const CC等价于const char[5],所以const CC&是对长度为5的const char数组的引用。- 局部变量绑定的特殊规则:当用字符串字面量绑定到数组引用时,C++标准允许隐式创建临时数组。这里
"ex"是const char[3],编译器会生成一个临时的const char[5]数组,把"ex"的内容复制进去(剩余位置补零),再将rcc绑定到这个临时对象上,这是标准允许的引用绑定临时对象的规则。 - 函数参数绑定的严格限制:函数参数传递时,数组类型的匹配要求完全一致(数组长度是类型的一部分)。
foo的参数要求是const char[5]的引用,而传入的"ex"是const char[3],属于不同的数组类型,编译器无法自动进行隐式转换,因此编译失败。 bar函数的差异:bar的参数是未知长度的数组引用const char(&)[]。C20之前的标准不允许这种引用绑定到字符串字面量,但C20放宽了规则,允许其绑定任意长度的字符串字面量,所以bar("ex")仅在C++20标准下编译通过。
总结
局部变量的数组引用可以通过隐式创建临时数组的方式绑定到短字符串字面量,但函数参数的数组引用要求类型完全匹配(包括数组长度),无法触发这种隐式转换,因此出现同类型绑定行为不同的情况。
内容的提问来源于stack exchange,提问作者user3240228
相关产品推荐
相关产品推荐

