[英]Does default parameterizing in C++ functions push the default values onto stack?
如果一個函數有20個參數(指針)(示例中使用了4個),並且所有參數的默認值都指向NULL,那是否意味着每次調用此函數都會在運行時執行PUSH堆棧NULL值?
這樣的函數示例可能如下所示:
function test(val1=NULL, val2=NULL, .... val20=NULL)
我要求最大限度地提高速度,並在函數調用期間減少#cycle。
// ArgsListTest.cpp
// @author Mathew Kurian
#include "stdafx.h"
#include <iostream>
#include <time.h>
using namespace std;
// Look at the difference in psuedo-assembly code
// My knowledge in compiler is little, but I can see that
// that there are unncessary cycles being wasted for this part.
// **** With array (this example) *****
// LOAD Reg, memAddressOfArray
// WRITETOMEM Reg, ptrToVar1
// INCREMENT sp
// WRITETOMEM Reg, ptrToVar2
// DECREMENT sp
// PUSH ptrToArray
// JUMP test
// ***** IDEALLY SUPPOSED TO LIKE THIS *****
// PUSH ptrToVar2
// PUSH ptrToVar1
// JUMP test
class Base
{
public:
virtual int test(void* arguments[])
{
cout << "Base function being called. VTable lookup ignored since there is no virtual." << endl;
cout << *static_cast<int*>(arguments[0]) << endl; // Parameter 1 (Thinks there is only 1 parameter!)
int x = 5; x += 1; // Random math to prevent optimizations. (I hope)
return x;
}
};
class Derived : public Base
{
public:
virtual int test(void* arguments[])
{
// cout << "Derived function being called. VTable lookup during runtime. Slight overhead here!" << endl;
// cout << *static_cast<string*>(arguments[0]) << endl; // Parameter 1
// cout << *static_cast<int*>(arguments[1]) << endl; // Parameter 2
int x = 5; x += 1;
return x;
}
};
class Base2
{
public:
virtual int test(void* arg1 = NULL, void* arg2 = NULL, void* arg3 = NULL, void* arg4 = NULL)
{
// cout << "Base2 function being called. VTable lookup ignored since there is no virtual." << endl;
// cout << *static_cast<string*>(arg1) << endl; // Parameter 1
// cout << *static_cast<int*>(arg2) << endl; // Parameter 2
int x = 5; x += 1;
return x;
}
virtual int test2()
{
int x = 5; x += 1;
return x;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Base * base = new Derived;
Base2 * base2 = new Base2;
int r = 0;
string * str = new string("sunny");
int * vale = new int(20);
int iterations = 1000000000;
//================================================================================
printf("Using No-Parameters [%d iterations]\n", iterations);
clock_t tStart = clock();
for (int x = 0; x < iterations; x++)
{
r = base2->test2();
}
printf("Time taken: %.9fs\n", (double)(clock() - tStart) / CLOCKS_PER_SEC);
//================================================================================
printf("Using Array [%d iterations]\n", iterations);
tStart = clock();
for (int x = 0; x < iterations; x++)
{
void * arguments[] = { str, vale };
r = base->test(arguments);
}
printf("Time taken: %.9fs\n", (double)(clock() - tStart) / CLOCKS_PER_SEC);
//================================================================================
printf("Using Default-Parameters [%d iterations]\n", iterations);
tStart = clock();
for (int x = 0; x < iterations; x++)
{
r = base2->test(str, vale);
}
printf("Time taken: %.9fs\n", (double)(clock() - tStart) / CLOCKS_PER_SEC);
//================================================================================
// cout << "NOTE: Derived class has no extra methods although the parameter counts are different.\n Parent class doesn't even realize parameter 1 exists!" << endl;
std::getchar();
return 0;
}
PUSH NULL
更快? 也許虛擬方法會影響您的結果。 我將您的方法復制到全局范圍,演示了不同的性能順序。
Using No-Parameters [1000000000 iterations]
Time taken: 24.831000000s
Using Array [1000000000 iterations]
Time taken: 24.730000000s
Using Default-Parameters [1000000000 iterations]
Time taken: 25.241000000s
Using No-Parameters [1000000000 iterations] on int testA()
Time taken: 21.664000000s
Using Array [1000000000 iterations] on int testB(void* arguments[])
Time taken: 22.384000000s
Using Default-Parameters [1000000000 iterations] int testC(void* arg1 = NULL, ...)
Time taken: 22.329000000s
編輯:
testB中數組賦值的相同測試移出for循環的范圍:
Using No-Parameters [1000000000 iterations]
Time taken: 24.713000000s
Using Array [1000000000 iterations]
Time taken: 24.686000000s
Using Default-Parameters [1000000000 iterations]
Time taken: 25.225000000s
Using No-Parameters [1000000000 iterations] on int testA()
Time taken: 21.653000000s
Using Array [1000000000 iterations] on int testB(void* arguments[])
Time taken: 21.896000000s
Using Default-Parameters [1000000000 iterations] int testC(void* arg1 = NULL, ...)
Time taken: 22.353000000s
也許。 另一個簡單的解決方案是擁有多個入口點:
# Pseudocode
PUSH nullptr # Default argument 20
PUSH nullptr # Default argument 19
PUSH nullptr # Default argument 18
...
ENTRYPOINT(test)
如果您有N個默認參數,則跳轉到常規入口點前面的地址N指令。 好處:推送這些默認參數的代碼現在可以在調用者之間共享。 但是,需要一點鏈接器智能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.