C++ 未使用的默认参数是否会降低性能c++;

C++ 未使用的默认参数是否会降低性能c++;,c++,performance,function,arguments,default-arguments,C++,Performance,Function,Arguments,Default Arguments,假设我声明了一个函数foo(intarg1,intarg2=0,intarg3=0,intarg4=0)。最后三个参数只会偶尔指定(如果有),并且大多数情况下,该函数将被称为foo(some_int)。如果我将函数声明为foo(int arg1),并使用不同的解决方案来传递其他参数(如果确实需要的话),我会获得性能吗 换句话说,声明但未指定的默认参数是否会使函数调用变慢? 本例中的函数是对象的构造函数,但这是一个一般性问题。(如果您愿意,您可以在结尾处阅读结论) 我做了一个基准测试来测试这个,我

假设我声明了一个函数
foo(intarg1,intarg2=0,intarg3=0,intarg4=0)
。最后三个参数只会偶尔指定(如果有),并且大多数情况下,该函数将被称为
foo(some_int)
。如果我将函数声明为
foo(int arg1)
,并使用不同的解决方案来传递其他参数(如果确实需要的话),我会获得性能吗

换句话说,声明但未指定的默认参数是否会使函数调用变慢?

本例中的函数是对象的构造函数,但这是一个一般性问题。

(如果您愿意,您可以在结尾处阅读结论)

我做了一个基准测试来测试这个,我首先运行了这个简短的程序大约十次:

#include <iostream>
#include <ctime>

using namespace std;

int returnMe(int me)
{
    return me;
}


int main()
{
   float begin = (float)clock();
   for(int i = 0; i < 100000000; i++)
   {
       int me = returnMe(i);
   }
   printf("\nTime: %f\n", begin);
   printf("\nTime: %f\n", (float)clock());

   return 0;
}
大约十次,现在的数值在584毫秒到624毫秒之间

结论:是的,这将使函数调用变慢,但速度非常小。创建一个单独的函数,将其他参数传递给对象,或者使用不同的构造函数,这将提高性能,但是否值得额外编写代码

Box2D使用另一种解决方法,基本上是为默认参数创建一个单独的结构,并将指针传递给它的实例。这样,当不需要设置额外的参数时,传递的唯一降低性能的“垃圾参数”是一个nullpointer,这并不是那么糟糕。当您想要指定一些默认值时,您可以在堆栈中创建所述结构的实例,填写所需的值,然后将其地址传递给函数。简单、优雅、高效

但是:两种建议的节省性能的解决方案(一个额外的函数和传递一个结构指针)都需要额外的代码。如果您的函数很少被调用,并且额外的参数也不多,那么保存的性能很可能根本不会有任何区别,如果是这样,那么就不值得您花费时间仅在必要时进行优化。还记得我添加了12个默认参数,甚至没有将函数调用时间增加一倍。

======== 编辑:严重测试的奖励

因此,前两个测试是使用简单的编译命令
g++test.cpp-o test.exe
完成的。正如许多评论中指出的,这意味着优化级别为-O0。我们在-O3下测试会得到什么结果

我重复了现在使用
g++test.cpp-o test.exe-O3编译的测试,但发现程序现在在1-2毫秒内完成。我尝试将迭代次数增加到1万亿次,然后是100万亿次,结果相同。所以我想g++可能看到我声明了一个不打算使用的变量,因此可能跳过了对
returnMe
的调用,也可能跳过了整个循环

为了得到一些有用的结果,我在
returnMe
中添加了实际的功能,以确保它没有被优化。以下是使用的程序:

#include <iostream>
#include <ctime>

using namespace std;

long long signed int bar = 0;

int returnMe(int me)
{
    bar -= me;
    return me;
}


int main()
{
   float begin = (float)clock();
   for(int i = 0; i < 1000000000; i++)
   {
       int me = returnMe(i);
       bar -= me * 2;
   }
   printf("\nTime: %f\n", begin);
   printf("\nTime: %f\n", (float)clock());
   printf("Bar: %i\n", bar);

   return 0;
}
#包括
#包括
使用名称空间std;
长符号整型条=0;
int returnMe(int me)
{
酒吧-=我;
还我;
}
int main()
{
浮点开始=(浮点)时钟();
对于(int i=0;i<100000000;i++)
{
int me=returnMe(i);
bar-=me*2;
}
printf(“\n时间:%f\n”,开始);
printf(“\n时间:%f\n”,(浮点)时钟();
printf(“条:%i\n”,条);
返回0;
}

#包括
#包括
使用名称空间std;
长符号整型条=0;
int returnMe(int-me,int-me87=0,int-m8e=0,int-m5e=0,int-m34e=0,int-m1e=0,int-me234=0,int-me332=0,int-me43=0,int-me34=0,int-me3=0,int-me2=0,int-me1=0)
{
酒吧-=我;
还我;
}
int main()
{
浮点开始=(浮点)时钟();
对于(int i=0;i<100000000;i++)
{
int me=returnMe(i);
bar-=me*2;
}
printf(“\n时间:%f\n”,开始);
printf(“\n时间:%f\n”,(浮点)时钟();
printf(“条:%i\n”,条);
返回0;
}
结果:

第一个程序:从653毫秒到686毫秒

第二个程序:从652毫秒到735毫秒


正如我所料,第二个程序仍然比第一个程序慢,但差别现在不那么明显。

这将取决于您的编译器、启用的优化以及函数是否是内联的

如果函数/构造函数是内联的,编译器可能会对此进行优化。如果函数不是内联的,则每次调用都会将值推送到堆栈中,因此会对性能产生影响(无论是否显著)


但请记住,过早优化是万恶之源。在运行概要文件之前,不要以为这会是一件大事,并编写一个不太容易维护的代码来绕过它,确保它需要优化。

这是什么优化级别和编译器?@Ludwik您应该使用-O3或至少-O2进行测试。切勿在未启用优化的情况下测试性能,因为您不应在未启用优化的情况下发布,因此在未启用优化的情况下测试性能是毫无意义的。@Ludwik,任何现代优化编译器都将消除您对
returnMe()
的调用,甚至取消
for
循环本身的调用。这个基准测试你做错了。也许你有什么东西在运行,这会减慢第二个程序的执行。对于基准测试,你应该选择所有运行中的最小时间(即,来自后台进程的入侵最少),因此这两个程序都是如预期的那样高效。您还应该检查生成的asm代码,以查看它们是否等效。具体取决于。如果按值传递复杂对象,则会增加开销。如果代码是内联的,则未使用的参数可能会被优化掉。
#include <iostream>
#include <ctime>

using namespace std;

long long signed int bar = 0;

int returnMe(int me)
{
    bar -= me;
    return me;
}


int main()
{
   float begin = (float)clock();
   for(int i = 0; i < 1000000000; i++)
   {
       int me = returnMe(i);
       bar -= me * 2;
   }
   printf("\nTime: %f\n", begin);
   printf("\nTime: %f\n", (float)clock());
   printf("Bar: %i\n", bar);

   return 0;
}
#include <iostream>
#include <ctime>

using namespace std;

long long signed int bar = 0;

int returnMe(int me, int me87 = 0, int m8e = 0, int m5e = 0, int m34e = 0,int m1e = 0,int me234 = 0,int me332 = 0,int me43 = 0,int me34 = 0,int me3 = 0,int me2 = 0,int me1 = 0)
{
    bar -= me;
    return me;
}

int main()
{
   float begin = (float)clock();
   for(int i = 0; i < 1000000000; i++)
   {
       int me = returnMe(i);
       bar -= me * 2;
   }
   printf("\nTime: %f\n", begin);
   printf("\nTime: %f\n", (float)clock());
   printf("Bar: %i\n", bar);

   return 0;
}