我们有一个庞大的C++代码库,有很多COM对象.暴露给COM的每个函数都必须具有__stdcall
调用约定(通常是STDMETHODCALLTYPE
宏),因此我们标记了许多函数STDMETHODCALLTYPE
.
现在我看到一个函数不是通过COM直接调用的,而只是从我们的C++代码中调用,而且这个函数STDMETHODCALLTYPE
在其签名中也有宏.我完全确定宏在那里没用 - 没有通过COM调用该函数.
我应该删除__stdcall
它,使其成为"默认"调用约定函数吗?我该如何做出这样的决定?
我的方法是使用内部代码的默认编译器调用约定,并对跨模块边界导出的任何方法使用明确定义的显式调用约定.
大多数编译器的默认调用约定出于性能原因而充分利用了寄存器,因此在适当的地方使用寄存器是有好处的.它还使您的代码更容易,因为您不需要指定约定来获取默认值.
对于导出的函数,您显然需要指定约定.如果您正在创建一个预期将使用C或C++以外的语言调用的库,那么使用stdcall是常规的.如果您只期望C或C++客户端,那么cdecl可能是最常见的约定.
当Windows从__ cdecl切换到_ _stdcall作为默认调用约定时,产品的大小下降了大约10%.这节省完全与在调用stdcall方法后删除堆栈调整有关(__cdecl是"调用堆栈以调整堆栈以删除参数"调用约定,__ stdcall是"callee调整堆栈以删除参数"调用约定,因为还有更多调用者比被调用者,切换减少二进制文件的大小).
使用__stdcall的缺点是你没有变量#s of argments(因为被调用者调整了堆栈,他们无法知道调用者指定了多少参数).
底线:从"默认"调用约定切换到__stdcall可能会导致二进制文件的大小减小.这对你来说可能重要,也可能不重要.
然而如前所述mkaes,如果您的代码EVER在另一个compiland访问(例如,如果你提供一个.LIB文件给别人),这是绝对关键的是你声明所用的调用约定.