我对函数参数列表中的默认值有一些疑问
1)默认值是签名的一部分吗?那么默认参数的参数类型呢?
2)存储的默认值在哪里?在堆栈或全局堆中还是在常量数据段中?
谢谢!
答案 0 :(得分:17)
不,默认参数不是签名的一部分,也不是函数类型的一部分。
参数类型是签名的一部分。但是默认参数类型对参数类型没有影响,即默认参数类型对签名没有影响。
默认参数不会在任何地方“存储”。默认参数是“语法糖”,仅在程序编译期间存在(作为默认参数)。如果在编译期间编译器注意到某些参数丢失,它将使用您指定的默认参数。默认参数的评估是在调用者的上下文中完成的。如果将临时对象指定为默认参数,则每次使用默认参数调用函数时都会创建单独的临时对象,并在调用表达式结束后立即销毁。
void foo(T t = T());
// A new temporary will be used as an argument every time you call it as `foo()`
foo();
// Equivalent to `foo(T())`. A temporary is created here, passed as an argument and
// destroyed afterwards, just like an explicit temporary would be
如果将具有静态存储持续时间的现有对象指定为默认参数,则它将存储在您定义它的任何位置。
T global;
void foo(T& t = global);
// In this case you are using a global object as a default argument
// It is you who "store" it wherever you want to store it
foo();
// Equivalent to `foo(global)`
如果声明默认参数但从未实际使用过它们,即如果每次都明确指定参数,则编译后的程序将无法获得这些参数的跟踪(这就是我称之为编译时“语法糖”的原因) )。
P.S。要包含Johannes在下面的评论中所说的内容:即使默认参数(使用时)在调用时在调用者的上下文中进行评估,也不是通过“textual substitution”来完成,因为可能会出现在我的示例中以上。最值得注意的是,默认参数中使用的名称的名称查找是在函数声明中指定默认参数时完成的,而不是在调用者的评估点。
答案 1 :(得分:1)
1)默认值是签名的一部分吗?
没有
默认参数的参数类型怎么样?
类型始终在签名中(如果您没有extern "..."
),无论它是否具有默认值。
2)存储的默认值在哪里?
无处。它们由编译器自动填充。
答案 2 :(得分:1)
1)如果参数没有任何默认值,则具有默认参数的函数的类型/签名与函数的类型/签名相同:
// foo1 and foo2 are both functions taking an int, and returning an int.
int foo1(int);
int foo2(int a = 0);
typedef int(*int_fn_ptr)(int);
int_fn_ptr f1 = foo1; // OK, assigning a function pointer
int_fn_ptr f2 = foo2; // OK
typedef int(*void_fn_ptr)(void);
void_fn_ptr f3 = foo2; // doesn't compile
2)调用函数时,调用者创建默认值。实际上,编译器只是替换:
foo2();
使用:
foo2(0);
一见到它。这就是为什么必须在函数声明的地方指定默认值,其中调用者可以看到它们。
在其他一些语言中,默认值“属于”函数本身。询问默认值“存储”的位置可能是有意义的,但在C ++中并非如此。
答案 3 :(得分:0)
// declaration
void func( int param = 3 );
//...
int main( void )
{
// doing
func();
// will probably give the same assembly as doing
func(3);
}
所以在调用func之前,它只会像任何其他参数一样推送3。
请注意,这只是猜测。