在默认参数结束之前,C ++编译器不会警告缺少参数

时间:2015-03-04 18:33:43

标签: c++ compiler-warnings default-arguments

我用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 *)

我可以在编译期间打开哪些选项来触发有关此错误使用的警告?

4 个答案:

答案 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