为什么没有参数标识符的函数在c++中有效?

时间:2022-03-13 22:35:29

Given a function in C++ with arguments that are only types and have no identifiers,

假设在c++中有一个函数,它的参数只有类型,没有标识符,

 void foo1(int, int, int){cout << "called foo1";}

I can call it as such:

我可以这样称呼它:

int main()
{
    foo1(10, 10, 10);
}

Why is this a valid construct in C++? Is this just an idiosyncrasy of C++, or does this kind of declaration actually have some purpose? Can we actually access the arguments that have been passed in somehow? (This kind of method declaration will not work in Java.)

为什么在c++中这是一个有效的构造?这只是c++的一种特性,还是这种声明实际上有什么意义?我们真的可以访问传入的参数吗?(这种方法声明在Java中不能工作。)

5 个解决方案

#1


35  

Consider a case where you are required to provide a function that meets the following prototype

考虑这样一种情况:您需要提供满足以下原型的函数

void dostuff(int x, int y, int z);

And say you are operating in a 2D space and do not use z inside your implementation. You can

假设你在二维空间中操作,在实现中不使用z。你可以

void dostuff(int x, int y, int z)
{
    // use x and y
}

and just ignore z, but the compiler will likely spot that you have defined but not used z and warn you that you could be making a mistake. Instead you can

忽略z,编译器可能会发现你已经定义了但没有使用z,并警告你可能会出错。相反,你可以

void dostuff(int x, int y, int )
{
    // use x and y
}

and leave out the definition of z. The compiler will accept and silently discard the third parameter because it knows you don't want it.

去掉z的定义,编译器就会接受并悄悄地丢弃第三个参数,因为它知道你不需要它。

You do not want to simply turn off the warning because of errors like this

您不希望仅仅因为这样的错误而关闭警告

void dostuff(int x, int y, int z)
{
    for (int z = 0; z < MAX; z++)
    {
        // use x and y and z, the local z. 
    }
}

Where a poorly-named loop index shadows the parameter z. The caller's input is now ignored and this could have bad consequences. This error is often hard to spot with the mark 1 eyeball, especially if the local z is buried somewhere deep in a complex function.

当一个命名不佳的循环索引阴影参数z时,调用者的输入现在被忽略了,这可能会产生不好的后果。这个错误通常很难用标记1的眼球来发现,特别是如果局部z被深埋在一个复杂的函数中。

Anytime the compiler can pick off a possible bug in your code, take advantage. It means less work for you.

任何时候,编译器都可以在你的代码中找出一个可能的错误,好好利用它。这意味着你的工作量减少了。

#2


14  

A declaration like

这样的声明

void foo1(int, int, int){cout << "called foo1";}

clearly shows in the declaration, that you want to fulfill a requirement with your function - e.g. override a specific function in the base class or interface, which e.g. could be declared there as

在声明中清楚地表明,您希望使用您的函数来满足需求——例如,覆盖基类或接口中的特定函数,例如,可以在那里声明为

virtual void foo1(int something, int another, int andAnother) = 0;

BUT you don't intend to use the parameters which are handed over to you.

但是你不打算使用交给你的参数。

Another example would be if you want to hand over the function to e.g. another function which expects a function pointer to a void function with three int parameters.

另一个例子是如果你想把函数交给例如,另一个函数,它期望一个函数指针指向一个具有三个int参数的void函数。

void giveMeFoo( void (*fn)(int, int, int) ) { ... }

Additionally, higher warning levels issue a warning, if parameters are declared, which are not evaluated in the function body. You can avoid that by leaving the parameter names away.

此外,如果已声明参数,则更高的警告级别会发出警告,但在函数体中不会对参数进行评估。可以通过保留参数名来避免这种情况。

The parameters without names are then indeed not accessible in the function body anymore - on purpose. user4581301 has nicely described, why.

没有名字的参数,在功能体中确实是不可访问的。user4581301很好地描述了为什么。

Declaring a standalone function without parameter names as in your example is allowed because of the usages described above, but it obviously makes no sense in most cases. An example where it does make sense is in the comment section. Another example of a standalone function without parameter names could be, if your'e writing a library and want to either maintain backward compatibility (your library function does not need the parameter anymore, but you don't want to break the public header declaration) or you want to reserve a parameter for future use.

在您的示例中声明一个没有参数名称的独立函数是允许的,因为上面描述了这些用法,但是在大多数情况下显然是没有意义的。注释部分给出了一个有意义的例子。独立的函数没有参数名称的另一个例子可能是,如果你说写一个图书馆,想保持向后兼容性(你的库函数不需要参数了,但是你不想打破公共头宣言)或者你想预订一个参数,以供将来使用。

#3


9  

Yes. It is legal in C++.

是的。它在c++中是合法的。

C++11 n3337 standard 8.4.1(p6) Function definitions:

C++11 n3337标准8.4.1(p6)函数定义:

Note: Unused parameters need not be named. For example,

注意:不需要命名未使用的参数。例如,

void print(int a, int) {
    std::printf("a = %d\n", a);
}

C++14 standard:

c++标准:14

[ 8.3.5.11] An identifier can optionally be provided as a parameter name; if present in a function definition , it names a parameter (sometimes called “formal argument”). [Note: In particular, parameter names are also optional in function definitions and names used for a parameter in different declarations and the definition of a function need not be the same.]

[8.3.5.11]可选地提供标识符作为参数名;如果在函数定义中出现,它将命名一个参数(有时称为“形式参数”)。[注意:在函数定义中,参数名称也是可选的,在不同的声明中,参数的名称是可选的,函数的定义不需要相同。]

#4


8  

It's legal, and if you're wondering why:

这是合法的,如果你想知道为什么:

Typically, unnamed arguments arise from the simplification of code or from planning ahead for extensions. In both cases, leaving the argument in place, although unused, ensures that callers are not affected by the change.

通常,未命名的参数来自于代码的简化或扩展的提前计划。在这两种情况下,保留参数(尽管未使用)可以确保调用者不受更改的影响。

Excerpt From: Bjarne Stroustrup. “The C++ Programming Language, Fourth Edition.”

摘录:内定。“c++编程语言,第四版。”

#5


1  

The idea is that you might want to change the function definition to use the placeholder later, without changing all the code where the function is called.

其思想是,您可能希望稍后更改函数定义以使用占位符,而不更改调用函数的所有代码。

Arguments in a function declaration can be declared without identifiers. When these are used with default arguments, it can look a bit funny. You can end up with :

函数声明中的参数可以在没有标识符的情况下声明。当这些参数与默认参数一起使用时,它看起来可能有点有趣。你可以这样结束:

void f(int x, int = 0, float = 1.1);

In C++ you don’t need identifiers in the function definition, either:

在c++中,函数定义中也不需要标识符:

void f(int x, int, float flt) { /* ... */ }

In the function body, x and flt can be referenced, but not the middle argument, because it has no name. Function calls must still provide a value for the placeholder, though: f(1) or f(1,2,3.0). This syntax allows you to put the argument in as a placeholder without using it.

在函数体中,可以引用x和flt,但不能引用中间参数,因为它没有名称。函数调用仍然必须为占位符提供一个值:f(1)或f(1,2,3.0)。这种语法允许您将参数作为占位符放入,而不使用它。

#1


35  

Consider a case where you are required to provide a function that meets the following prototype

考虑这样一种情况:您需要提供满足以下原型的函数

void dostuff(int x, int y, int z);

And say you are operating in a 2D space and do not use z inside your implementation. You can

假设你在二维空间中操作,在实现中不使用z。你可以

void dostuff(int x, int y, int z)
{
    // use x and y
}

and just ignore z, but the compiler will likely spot that you have defined but not used z and warn you that you could be making a mistake. Instead you can

忽略z,编译器可能会发现你已经定义了但没有使用z,并警告你可能会出错。相反,你可以

void dostuff(int x, int y, int )
{
    // use x and y
}

and leave out the definition of z. The compiler will accept and silently discard the third parameter because it knows you don't want it.

去掉z的定义,编译器就会接受并悄悄地丢弃第三个参数,因为它知道你不需要它。

You do not want to simply turn off the warning because of errors like this

您不希望仅仅因为这样的错误而关闭警告

void dostuff(int x, int y, int z)
{
    for (int z = 0; z < MAX; z++)
    {
        // use x and y and z, the local z. 
    }
}

Where a poorly-named loop index shadows the parameter z. The caller's input is now ignored and this could have bad consequences. This error is often hard to spot with the mark 1 eyeball, especially if the local z is buried somewhere deep in a complex function.

当一个命名不佳的循环索引阴影参数z时,调用者的输入现在被忽略了,这可能会产生不好的后果。这个错误通常很难用标记1的眼球来发现,特别是如果局部z被深埋在一个复杂的函数中。

Anytime the compiler can pick off a possible bug in your code, take advantage. It means less work for you.

任何时候,编译器都可以在你的代码中找出一个可能的错误,好好利用它。这意味着你的工作量减少了。

#2


14  

A declaration like

这样的声明

void foo1(int, int, int){cout << "called foo1";}

clearly shows in the declaration, that you want to fulfill a requirement with your function - e.g. override a specific function in the base class or interface, which e.g. could be declared there as

在声明中清楚地表明,您希望使用您的函数来满足需求——例如,覆盖基类或接口中的特定函数,例如,可以在那里声明为

virtual void foo1(int something, int another, int andAnother) = 0;

BUT you don't intend to use the parameters which are handed over to you.

但是你不打算使用交给你的参数。

Another example would be if you want to hand over the function to e.g. another function which expects a function pointer to a void function with three int parameters.

另一个例子是如果你想把函数交给例如,另一个函数,它期望一个函数指针指向一个具有三个int参数的void函数。

void giveMeFoo( void (*fn)(int, int, int) ) { ... }

Additionally, higher warning levels issue a warning, if parameters are declared, which are not evaluated in the function body. You can avoid that by leaving the parameter names away.

此外,如果已声明参数,则更高的警告级别会发出警告,但在函数体中不会对参数进行评估。可以通过保留参数名来避免这种情况。

The parameters without names are then indeed not accessible in the function body anymore - on purpose. user4581301 has nicely described, why.

没有名字的参数,在功能体中确实是不可访问的。user4581301很好地描述了为什么。

Declaring a standalone function without parameter names as in your example is allowed because of the usages described above, but it obviously makes no sense in most cases. An example where it does make sense is in the comment section. Another example of a standalone function without parameter names could be, if your'e writing a library and want to either maintain backward compatibility (your library function does not need the parameter anymore, but you don't want to break the public header declaration) or you want to reserve a parameter for future use.

在您的示例中声明一个没有参数名称的独立函数是允许的,因为上面描述了这些用法,但是在大多数情况下显然是没有意义的。注释部分给出了一个有意义的例子。独立的函数没有参数名称的另一个例子可能是,如果你说写一个图书馆,想保持向后兼容性(你的库函数不需要参数了,但是你不想打破公共头宣言)或者你想预订一个参数,以供将来使用。

#3


9  

Yes. It is legal in C++.

是的。它在c++中是合法的。

C++11 n3337 standard 8.4.1(p6) Function definitions:

C++11 n3337标准8.4.1(p6)函数定义:

Note: Unused parameters need not be named. For example,

注意:不需要命名未使用的参数。例如,

void print(int a, int) {
    std::printf("a = %d\n", a);
}

C++14 standard:

c++标准:14

[ 8.3.5.11] An identifier can optionally be provided as a parameter name; if present in a function definition , it names a parameter (sometimes called “formal argument”). [Note: In particular, parameter names are also optional in function definitions and names used for a parameter in different declarations and the definition of a function need not be the same.]

[8.3.5.11]可选地提供标识符作为参数名;如果在函数定义中出现,它将命名一个参数(有时称为“形式参数”)。[注意:在函数定义中,参数名称也是可选的,在不同的声明中,参数的名称是可选的,函数的定义不需要相同。]

#4


8  

It's legal, and if you're wondering why:

这是合法的,如果你想知道为什么:

Typically, unnamed arguments arise from the simplification of code or from planning ahead for extensions. In both cases, leaving the argument in place, although unused, ensures that callers are not affected by the change.

通常,未命名的参数来自于代码的简化或扩展的提前计划。在这两种情况下,保留参数(尽管未使用)可以确保调用者不受更改的影响。

Excerpt From: Bjarne Stroustrup. “The C++ Programming Language, Fourth Edition.”

摘录:内定。“c++编程语言,第四版。”

#5


1  

The idea is that you might want to change the function definition to use the placeholder later, without changing all the code where the function is called.

其思想是,您可能希望稍后更改函数定义以使用占位符,而不更改调用函数的所有代码。

Arguments in a function declaration can be declared without identifiers. When these are used with default arguments, it can look a bit funny. You can end up with :

函数声明中的参数可以在没有标识符的情况下声明。当这些参数与默认参数一起使用时,它看起来可能有点有趣。你可以这样结束:

void f(int x, int = 0, float = 1.1);

In C++ you don’t need identifiers in the function definition, either:

在c++中,函数定义中也不需要标识符:

void f(int x, int, float flt) { /* ... */ }

In the function body, x and flt can be referenced, but not the middle argument, because it has no name. Function calls must still provide a value for the placeholder, though: f(1) or f(1,2,3.0). This syntax allows you to put the argument in as a placeholder without using it.

在函数体中,可以引用x和flt,但不能引用中间参数,因为它没有名称。函数调用仍然必须为占位符提供一个值:f(1)或f(1,2,3.0)。这种语法允许您将参数作为占位符放入,而不使用它。