【转】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> & ...
随机推荐
- 文件夹或者文件比对工具 Beyond Compare
文件夹或者文件比对工具 Beyond Compare 之前有同事离职了. 没有工作交接. 同事的代码有一部分也没有提交版本库. 结果就是线上的代码和版本库中的文件数 ...
- synchronized和volatile比较
synchronized和volatile比较 volatile不需要加锁,比synchronized更轻量级,不会阻塞线程 从内存可见性角度讲,volatile读相当于加锁,volatile写相当于 ...
- Java Web 高性能开发,第 1 部分: 前端的高性能
Web 发展的速度让许多人叹为观止,层出不穷的组件.技术,只需要合理的组合.恰当的设置,就可以让 Web 程序性能不断飞跃.所有 Web 的思想都是通用的,它们也可以运用到 Java Web.这一系列 ...
- Touch Handling in Cocos2D 3.x(五)
实现新英雄的放置功能 首先我们需要一个变量来保持我们当前移动英雄的引用,因此我们将添加一个私有实例变量.修改MainScene.m中的代码. 用: @implementation MainScene ...
- Maven nexus安装、配置和使用
简介 Nexus 可以代理并缓存 Maven 构件,当 Maven 需要下载构件的时候,就不需要反复的请求中央仓库. 有些公司都不提供外网给项目组人员,因此就不能使用 Maven 访问 ...
- Java序列化Serializable和Externalizable
纸上得来终觉浅,绝知此事要躬行 --陆游 问渠那得清如许,为有源头活水来 --朱熹 什么是Java序列化?为什么出现Java序列化?怎样实现Java序列化? 一.什么是Java序列化 ...
- Java学习笔记(三)Java2D组件
一 概述 Java2D的一切都基于java.awt包中的Graphics2D类,它是Graphics的子类. 为了绘制图形,需要使用面板作为画布,例如使用JPanel作为画布,面板有一个paintC ...
- 关于Service中bindService注意的几个问题
最近有用到Activity需要不断的从Service中获取数据,第一个想法肯定就是通过bind回调机制了,有几点概念模糊特此记录下: 单独使用bindService(),unbindService() ...
- 【Linux 操作系统】vim编辑器配置及常用命令
最近工作不安分, 没有了刚入行时候的锐气, 不知道什么时候开始懈怠起来, 周末在电脑旁边看新闻, 搞笑图片, 追美剧, 一坐就是一天, 很是空虚. 我需要摆脱这种状态, 正好想学习一下安卓底层, An ...
- Linux配置文件系统及程序的限制 - ulimit
想象一个状况:我的 Linux 主机里面同时登陆了十个人,这十个人不知怎么搞的, 同时开启了 100 个文件,每个文件的大小约 10MBytes ,请问一下, 我的 Linux 主机的内存要有多大才够 ...