【转】UNREFERENCED_PARAMETER的作用
UNREFERENCED_PARAMETER 的作用
我们从 UNREFERENCED_PARAMETER 开始吧。这个宏在 winnt.h 中定义如下:
#define UNREFERENCED_PARAMETER(P) (P)
换句话说
UNREFERENCED_PARAMETER
展开传递的参数或表达式。其目的是避免编译器关于未引用参数的警告。许多程序员,包括我在内,喜欢用最高级别的警告 Level
4(/W4)进行编译。Level 4
属于“能被安全忽略的事件”的范畴。虽然它们可能使你难堪,但很少破坏你的代码。例如,在你的程序中可能会有这样一些代码行:
int x=1;
但你从没用到过 x。也许这一行是你以前使用 x
时留下来的,只删除了使用它的代码,而忘了删除这个变量。Warning Level 4
能找到这些小麻烦。所以,为什么不让编译器帮助你完成可能是最高级别的专业化呢?用Level 4
编译是展示你工作态度的一种方式。如果你为公众使用者编写库,Level 4
则是社交礼节上需要的。你不想强迫你的开发人员使用低级选项清洁地编译他们的代码。
问题是,Level 4 实在是太过于注意细节,在 Level 4 上,编译器连未引用参数这样无伤大雅的事情也要抱怨(当然,除非你真的有意使用这个参数,这时便相安无事)。假设你有一个函数带来两个参数,但你只使用其中一个:
int SomeFunction(int arg1, int arg2){ return arg1+5;}
使用 /W4,编译器抱怨:
“warning C4100: ''arg2'' : unreferenced formal parameter.”
为了骗过编译器,你可以加上 UNREFERENCED_PARAMETER(arg2)。现在编译器在编译你的引用 arg2 的函数时便会住口。并且由于语句:
arg2;
实际上不做任何事情,编译器不会为之产生任何代码,所以在空间和性能上不会有任何损失。
细心的人可能会问:既然你不使用 arg2,那当初为何要声明它呢?通常是因为你实现某个函数以满足某些API固有的署名需要,例如,MFC的 OnSize 处理例程的署名必须要像下面这样:
void OnSize(UINT nType, int cx, int cy);
这里 cx/cy 是窗口新的宽/高,nType
是一个类似 SIZE_MAXIMIZED 或 SIZE_RESTORED 这样的编码,表示窗口是否最大化或是常规大小。一般你不会在意
nType,只会关注 cx 和 xy。所以如果你想用 /W4,则必须使用
UNREFERENCED_PARAMETER(nType)。OnSize 只是上千个 MFC 和 Windows 函数之一。编写一个基于
Windows 的程序,几乎不可能不碰到未引用参数。
说了这么多关于 UNREFERENCED_PARAMETER 内容。Judy 在她的问题中还提到了另一个 C++ 程序员常用的并且其作用与 UNREFERENCED_PARAMETER 相同的诀窍,那就是注释函数署名中的参数名:
void CMyWnd::OnSize(UINT /* nType */, int cx, int cy){}
现在 nType 是未命名参数,其效果就像你敲入 OnSize(UINT, int cx, int cy)一样。那么现在的关键问题是:你应该使用哪种方法——未命名参数,还是 UNREFERENCED_PARAMETER?
大多数情况下,两者没什么区别,使用哪一个纯粹是风格问题。(你喜欢你的 Java
咖啡是黑色还是奶油的颜色?)但我认为至少有一种情况必须使用
UNREFERENCED_PARAMETER。假设你决定窗口不允许最大化。那么你便禁用 Maximize
按钮,从系统菜单中删除,同时阻止每一个用户能够最大化窗口的操作。因为你是偏执狂(大多数好的程序员都是偏执狂),你添加一个 ASSERT
(断言)以确保代码按照你的意图运行:
void CMyWnd::OnSize(UINT nType, int cx, int cy){ ASSERT(nType != SIZE_MAXIMIZE); ... // use cx, cy}
质检团队竭尽所能以各种方式运行你的程序,ASSERT
从没有弹出过,于是你认为编译生成 Release 版本是安全的。但是此时 _DEBUG 定义没有了,ASSERT(nType !=
SIZE_MAXIMIZE)展开为 ((void)0),并且 nType 一下子成了一个未引用参数!这样进入你干净的编译。你无法注释掉参数表中的
nType,因为你要在 ASSERT 中使用它。于是在这种情况下——你唯一使用参数的地方是在 ASSERT 中或其它 _DEBUG
条件代码中——只有 UNREFERENCED_PARAMETER 会保持编译器在 Debug 和 Release
生成模式下都没有问题。知道了吗?
结束讨论之前,我想还有一个问题我没有提及,就是你可以象下面这样用 pragma 指令抑制单一的编译器警告:
#pragma warning( disable : 4100 )
4100 是未引用参数的出错代码。pragma 抑制其余文件/模块的该警告。用下面方法可以重新启用这个警告:
#pragma warning( default : 4100 )
不管怎样,较好的方法是在禁用特定的警告之前保存所有的警告状态,然后,等你做完之后再回到以前的配置。那样,你便回到的以前的状态,这个状态不一定是编译器的默认状态。
所以你能象下面这样在代码的前后用 pragma 指令抑制单个函数的未引用参数警告:
#pragma warning( push ) #pragma warning( disable : 4100 )void SomeFunction(...){}#pragma warning( pop )
当然,对于未引用参数而言,这种方法未免冗长,但对于其它类型的警告来说可能就不是这样了。库生成者都是用
#pragma warning 来阻塞警告,这样他们的代码可以用 /W4 进行清洁编译。MFC 中充满了这样的 pragmas
指令。还有好多的 #pragma warning 选项我没有在本文讨论。有关它们的信息请参考相关文档。
【转】UNREFERENCED_PARAMETER的作用的更多相关文章
- UNREFERENCED_PARAMETER()的作用
告诉编译器,已经使用了该变量,不必警告. 在VC编译器下,当你声明了一个变量,而没有使用时,编译器就会报警告: “warning C4100: ''XXXX'' : unreferenced form ...
- C++ UNREFERENCED_PARAMETER函数的作用
新建win32 application程序,会有这样一段代码 int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hP ...
- UNREFERENCED_PARAMETER
作用:告诉编译器,已经使用了该变量,不必检测警告! 在VC编译器下,如果您用最高级别进行编译,编译器就会很苛刻地指出您的非常细小的警告.当你生命了一个变量,而没有使用时,编译器就会报警告:" ...
- C++:UNREFERENCED_PARAMETER用法
原文地址:http://www.cnblogs.com/kex1n/archive/2010/08/05/2286486.html 作用:告诉编译器,已经使用了该变量,不必检测警告! 在VC编译器下, ...
- UNREFERENCED_PARAMETER的用处
UNREFERENCED_PARAMETER的用处 作用:告诉编译器,已经使用了该变量,不必检测警告! 在VC编译器下,如果您用最高级别进行编译,编译器就会很苛刻地指出您的非常细小的警告.当你生命了一 ...
- if __name__== "__main__" 的意思(作用)python代码复用
if __name__== "__main__" 的意思(作用)python代码复用 转自:大步's Blog http://www.dabu.info/if-__-name__ ...
- (转载)linux下各个文件夹的作用
linux下的文件结构,看看每个文件夹都是干吗用的/bin 二进制可执行命令 /dev 设备特殊文件 /etc 系统管理和配置文件 /etc/rc.d 启动的配置文件和脚本 /home 用户主目录的基 ...
- github中的watch、star、fork的作用
[转自:http://www.jianshu.com/p/6c366b53ea41] 在每个 github 项目的右上角,都有三个按钮,分别是 watch.star.fork,但是有些刚开始使用 gi ...
- web.xml中welcome-file-list的作用
今天尝试使用struts2+ urlrewrite+sitemesh部署项目,结果发现welcome-file-list中定义的欢迎页不起作用: <welcome-file-list> & ...
随机推荐
- Zeroc Ice Slice语言使用 HelloWorld
Slice介绍 为了开发多语言支持的RPC服务,需要一种中立的新语言来定义这个服务接口,以便各个编程语言能够准确无误地理解和翻译接口,为此Ice设计了Slice语言.Ice开发的第一步 ...
- Mybatis源码之Statement处理器RoutingStatementHandler(三)
RoutingStatementHandler类似路由器,在其构造函数中会根据Mapper文件中设置的StatementType来选择使用SimpleStatementHandler.Prepared ...
- RabbitMQ消息队列(六):使用主题进行消息分发
在上篇文章RabbitMQ消息队列(五):Routing 消息路由 中,我们实现了一个简单的日志系统.Consumer可以监听不同severity的log.但是,这也是它之所以叫做简单日志系统的原因, ...
- 数值分析:Hermite多项式
http://blog.csdn.net/pipisorry/article/details/49366047 Hermite埃尔米特多项式 在数学中,埃尔米特多项式是一种经典的正交多项式族,得名于法 ...
- ROS_Kinetic_07 ROS中机器人三维物理引擎高保真仿真利器gazebo 7.0
ROS_Kinetic_07 ROS中机器人三维物理引擎高保真仿真利器gazebo 7.0 ROS kinetic中的gazebo版本是7.0,有很多新的特性. 首先,启动gazebo: ~$ gaz ...
- (NO.00001)iOS游戏SpeedBoy Lite成形记(二十三)
现在还有一个视觉上的问题:玩家每次在游戏开始前选择某一赛道时,无法直观的看到所选的是哪条赛道.只能通过界面上方的gambleLabel中的文字非直观的看到.我们现在来完善它! 为了能让玩家清楚地看到, ...
- 集团公司(嵌入ETL工具)财务报表系统解决方案
集团公司(嵌入ETL工具)财务报表系统解决方案 一.项目背景: 某集团公司是一家拥有100多家子公司的大型集团公司,旗下子公司涉及各行各业,包括:金矿.铜矿.房产.化纤等.由于子公司在业务上的差异,子 ...
- Windows Mobile和Wince(Windows Embedded CE)的字符集问题
背景 开发过Windows Mobile和Wince(Windows Embedded CE)的开发者,特别是Native C++开发者,或多或少都遇到过ANSI字符集和Unicode字符集的转换问题 ...
- 64位ubuntu14.04配置adb后提示没有那个文件或目录
1.配置完adb环境变量后在终端输入adb: ameyume@ameyume-HP-450-Notebook-PC:~$ adb /home/ameyume/adt-bundle-linux-x86_ ...
- saiku中文维度,补充说明
saiku在筛选中文维度 会出现浏览器白屏 停止响应的现象,经过跟踪源代码,分析原来在linux 操作系统中 数据库读取的中文和界面选取的编码是不一致的 解决方法, classes\saiku-dat ...