当前位置: 首页 > news >正文

【转】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 选项我没有在本文讨论。有关它们的信息请参考相关文档。

转载于:https://www.cnblogs.com/PigDiaoing/p/6530822.html

相关文章:

  • Bootstrap框架下实现图片切换
  • SpringBoot学习之路:02.第一个程序Hello World及项目结构介绍
  • samba部署和优化
  • OSChina 周日乱弹 ——花季少女突然离开,昨夜他们做了什么?
  • VC++开发(一)——VC++自定义注释
  • 一个典型核心网络故障分析
  • 网站优化简单探讨
  • Maven 编译时复制 resources下的文件到主输出目录
  • 面试STAR法则
  • Comparable和Comparator接口
  • 驼峰法则
  • 记忆
  • Android系统篇之—-编写简单的驱动程序并且将其编译到内核源码中【转】
  • Linux系统基础网络配置
  • 研究生flag
  • Android 控件背景颜色处理
  • JAVA_NIO系列——Channel和Buffer详解
  • Java新版本的开发已正式进入轨道,版本号18.3
  • jquery cookie
  • JSDuck 与 AngularJS 融合技巧
  • Making An Indicator With Pure CSS
  • Mybatis初体验
  • Mysql5.6主从复制
  • PAT A1092
  • 从tcpdump抓包看TCP/IP协议
  • 经典排序算法及其 Java 实现
  • 怎么把视频里的音乐提取出来
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (0)Nginx 功能特性
  • (4)STL算法之比较
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (c语言)strcpy函数用法
  • (pojstep1.1.2)2654(直叙式模拟)
  • (动态规划)5. 最长回文子串 java解决
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (附源码)ssm捐赠救助系统 毕业设计 060945
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (四)鸿鹄云架构一服务注册中心
  • (转)大型网站架构演变和知识体系
  • (转)为C# Windows服务添加安装程序
  • **PHP分步表单提交思路(分页表单提交)
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .htaccess 强制https 单独排除某个目录
  • .net core 依赖注入的基本用发
  • .Net Framework 4.x 程序到底运行在哪个 CLR 版本之上
  • .net web项目 调用webService
  • /etc/skel 目录作用
  • []FET-430SIM508 研究日志 11.3.31
  • [BPU部署教程] 教你搞定YOLOV5部署 (版本: 6.2)