我用3个参数声明了一个C ++函数声明,其中两个默认值是这样的。
void func(int const n, bool const flag=true, int *array=NULL) {
/* print contents of array */
}
当我错误地调用该函数时,省略第二个参数但包含第三个参数,如此
int array[5]={1,2,3,4,5};
func(5,array);
gcc和intel编译器(Ubuntu 14.04 LTS上的默认编译器)都没有抱怨指定了最后一个参数而没有指定倒数第二个参数。代码运行但是为数组发送了NULL(我希望代码失败)。
我的问题是,为什么编译器没有抱怨它找不到匹配的函数,因为我的调用签名应该显示为
funct(int const, int *)
我可以在编译期间打开哪些选项来触发有关此错误使用的警告?
答案 0 :(得分:14)
编译器将数组衰减为指针并将指针转换为bool
并继续。
<强>更新强>
来自C ++ 11标准:
4次标准转化 [转化]
1标准转化是具有内置含义的隐式转化。第4条列举了全套这类 转换。 标准转换序列是按以下顺序进行的一系列标准转换:
- 来自以下集合的零或一次转换:左值到右值的转换,数组到指针的转换, 和函数到指针的转换。
- 来自以下集合的零或一次转换:整数促销,浮点促销,积分 转换,浮点转换,浮点积分转换,指针转换,指针指向 成员转换和布尔转换。
- 零或一个资格转换。
[注意:标准转换序列可以为空,即它可以不包含任何转换。 -end note ]
如果需要,标准转换序列将应用于表达式,以将其转换为所需的目标类型。
答案 1 :(得分:2)
在这种特殊情况下,解决方案可能使用不同的参数顺序:
void func(int const n, int *array=NULL, bool const flag=true ) {
/* print contents of array */
}
如果省略第二个参数布尔值不能隐式转换为指针(除非你有使用0作为false
的坏习惯),所以它将无法编译(或至少提供警告)。
void func(int const n, int *array = nullptr, bool const flag=true ) {
/* print contents of array */
}
int main()
{
func( 0, false );
}
警告:转换&#39; false&#39;到&#39; void的参数2的指针类型 func(int,int *,bool)&#39; [-Wconversion空]
但总的来说,它表明你应该使用不同的技术。例如,使用std::vector
而不是原始指针。
typedef std::vector<int> int_vec;
void func( bool const flag=true, const int_vec &array = int_vec() ) {
/* print contents of array */
}
int main()
{
int_vec array {1,2,3,4,5};
func( array );
}
错误:无法转换&#39; int_vec {aka std :: vector}&#39;到了布尔&#39;对于 论证&#39; 1&#39; to&#39; void func(bool,int_vec)&#39;
答案 2 :(得分:2)
根据C ++标准(4标准转换)
1标准转化是具有内置含义的隐式转化。 第4条列举了全套此类转换。一个标准 转换序列是一系列标准转换 以下顺序:
- 来自以下集合的零次或一次转换: 左值到右值的转换,数组到指针的转换,以及 函数到指针的转换。
- 来自以下集合的零或一次转换:积分 促销,浮点促销,积分转换,浮动 点转换,浮点积分转换,指针转换, 指向成员转换的指针,以及布尔转换。
- 零或一个资格转换。
和
4.12布尔转换
1算术,无范围枚举,指针或指针的prvalue 成员类型可以转换为bool类型的prvalue。零 value,null指针值或null成员指针值是 转换为假;任何其他值都转换为true。对于 直接初始化(8.5),类型为std :: nullptr_t的prvalue可以 转换为bool类型的prvalue;结果值为false。
所以这个函数调用
func(5,array);
相当于
func(5,array, NULL);
第一个参数首先从数组转换为指针(数组到指针转换),然后转换为布尔值true(布尔转换)。
因此,此调用是函数的有效调用。编译器隐式地将参数转换为适当的类型。
答案 3 :(得分:2)
有一个隐含的强制转换。
使用Visual C ++,您将收到C4800警告。
在gcc中,您可以使用以“-W”开头的选项请求特定警告,例如-Wimplicit
,以请求隐式声明的警告。有关完整文档,请参阅Options to Request or Suppress Warnings。