如果我们编译以下代码:

#include <stdio.h>

int main(int argc, char** argv)
{
    int n;
    int nRet = printf("Hello, world!");
    return 0;    
}

编译器一般会发出以下警告(VS2015):

1>f:\mycode\cpptest\main.cpp(55): warning C4100: “argv”: 未引用的形参
1>f:\mycode\cpptest\main.cpp(55): warning C4100: “argc”: 未引用的形参
1>f:\mycode\cpptest\main.cpp(67): warning C4101: “a”: 未引用的局部变量
1>f:\mycode\cpptest\main.cpp(68): warning C4189: “nRet”: 局部变量已初始化但不引用

编译器认为,既然我们已经声明/定义了某变量,那我们就有使用它的意图。所以当它检测到我们未对此变量进行实际的使用时,就会发出警告,提醒我们检查代码是否存在错误。

为了代码编译时输出窗口的整洁(以使有价值的提示信息更醒目),我们通常会消除掉此类警告(当然是在我们确认这是有意为之之后)。而在消除此类警告时,隐式地,我们一般有以下四种期望:

编译器不再发出此警告;
不会引起代码逻辑变化;
不会造成性能损失;
不会对代码维护造成负担,包括阅读和修改;
以下提供两种经典解决方案,并分析网上流传的一些方法为什么不可取。

一、宏UNREFERENCED_PARAMETER

Windows开发人员使用宏定义方案。在Windows平台下,可以在<winnt.h>中找到以下宏定义:

#define UNREFERENCED_PARAMETER(P)          (P)

使用方法如下:

int main(int argc, char** argv)
{
    UNREFERENCED_PARAMETER(argc); // 手动醒目
    UNREFERENCED_PARAMETER(argv); // 手动醒目

int n;
    UNREFERENCED_PARAMETER(n); // 手动醒目
    int nRet = printf("Hello, world!");
    UNREFERENCED_PARAMETER(nRet); // 手动醒目
    return 0;    
}

因为实际上,代码被宏展开为如下形式:

int main(int argc, char** argv)
{
    (argc); // 手动醒目
    (argv); // 手动醒目

int n;
    (n); // 手动醒目
    int nRet = printf("Hello, world!");
    (nRet); // 手动醒目
    return 0;    
}
,即argc、argv、n和nRet确实被使用(作为一条单独的语句),所以警告不会再产生。 
如果严格按照这样一个变量一条语句的写法,代码逻辑就绝不会发生变化;同时,在release模式下,这些代码完全会被优化掉,所以对性能也不会造成影响。

另外,宏的名称UNREFERENCED_PARAMETER已经说明,这是一个未被引用的参数,所以在阅读时不仅不会造成障碍,反而会有助于理解;而在代码修改时,如果真正使用了些变量,直接将此句删除,也是很简单的一件事。

但是,实际上在Windows中,此宏仅被用来消除warning C4100: 未引用的形参警告,因为宏的名称是UNREFERENCED_ PARAMETER。所以如果在我们的项目中应用此解决方案时,最好自己定义一个名称更应景的宏,譬如:

#define UNREFERENCED_VALUE(P)          (P)

以同时完美应用于上述三种警告。

二、模板空函数PX_UNUSED()

NVIDIA的PhysX项目开发人员使用模板空函数解决方案。在PhysX开源代码的include\foundation\PxPreprocessor.h中可以找到如下定义(同时还有某些对此方法的疑问,下面各节将会回答这些疑问):

// avoid unreferenced parameter warning (why not just disable it?)
// PT: or why not just omit the parameter's name from the declaration????
template <class T> PX_CUDA_CALLABLE PX_INLINE void PX_UNUSED(T const&) {}

使用方法如下:

int main(int argc, char** argv)
{
    PX_UNUSED(argc); // 手动醒目
    PX_UNUSED(argv); // 手动醒目

int n;
    PX_UNUSED(n); // 手动醒目
    int nRet = printf("Hello, world!");
    PX_UNUSED(nRet); // 手动醒目
    return 0;    
}

首先,原本未被引用的变量确实被用来调用函数了,所以警告被消除。应该注意到,在PX_UNUSED()实现时有一个细节,它没有给出参数的具体名称const T&,所以警告不会再传递(见“三、为什么不应该直接删除函数参数名”)。

其次,因为仅被用来调用空函数,且是传引用方法,所以代码逻辑不会被影响;而空函数在release模式下也会被优化掉,所以也不会产生性能影响,顶多在编译时生成模板函数增加了一点点时间。

最后,此函数被使用时,同样醒目且易删除,所以也不会对代码维护造成额外的负担。

相对于宏定义的方式,我比较赞成此种解决方案,因为前者有可能因为误用而造成莫名其妙的错误。
---------------------

原文:https://blog.csdn.net/u012494876/article/details/53400679

警告“未引用的形参/局部变量”的消除方法相关推荐

  1. Qt使用MSVC编译器关闭“C4100:未引用的形参”警告的方法

    Qt使用MSVC编译器关闭"C4100:未引用的形参"警告的方法 [问题描述] 在C++中,经常会定义一些虚函数作为接口类,这些虚函数本身基本是空函数,由派生类覆盖出具体的实现.一 ...

  2. 前端基础建设与架构11 Tree Shaking:移除 JavaScript 上下文中的未引用代码

    时至今日,Tree Shaking 对于前端工程师来说,已经不是一个陌生的名词了.顾名思义:Tree Shaking 译为"摇树",它通常用于描述移除 JavaScript 上下文 ...

  3. s5 android5.0内存泄漏,android-最初从位图泄漏了未引用的byte [],但被回收的()导致内存泄漏(直到活动停止)...

    我的位图内存泄漏导致内存不足.我在Android 5.0(Samsung S5)上运行了测试.我已经使用Android Studio(1.5.1 2.0.0预览版7)调查了此问题. HPROF内存转储 ...

  4. 警告: 未提供 -tsa 或 -tsacert, 此 jar 没有时间戳。如果没有时间戳, 则在签名者证书的到期

    在给生成的apk签名,jdk1.6升级到jdk1.7会出现以下问题: 1.明明签名了,并且签名检查apk中也有签名文件,但是安装的时候就是提示安装失败,没有签名,解决办法 将签名命令上加一段话: -d ...

  5. VS Code中如何关闭保存Go语言文件时自动去除未引用包的行为

    在使用Visual Studio Code编写Go语言(Golang)程序代码的时候,有时候引用的包明明是正确引用了,但在保存的时候却会被自动删除掉,是被误认为未引用了.这时候,参照以下步骤就可以解决 ...

  6. 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

    作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...

  7. java形参改变实参_java方法改变形参后得到实参值是否改变

    public voidtest1(){ String s= "1"; System.out.println("调用方法hange1前s的内存地址:"+Syste ...

  8. IOS 编程中引用第三方的方类库的方法及常见问题

    方法一:直接复制全部源文件到项目中 这样的方法就是把第三方类库的全部源文件复制到项目中.直接把全部.h和.m文件拖到XCode项目中就可以. 注意: 1. 假设第三方类库引用了一些系统自带类库.那么在 ...

  9. Java中 方法引用、Stream流、及方法实例 D190401

    Java中 方法引用.Stream流.及方法实例 D190401 01.第三章:方法引用_什么是方法引用 1).什么是"方法引用":指引用现有的方法代替Lambda表达式--当我们 ...

最新文章

  1. ASP.Net后台 实现先弹出对话框,再跳转到另一个网页的实现方法
  2. Compute API 关键概念 详解
  3. CUDA5.5入门文章:VS10设置
  4. CentOS中安装Docker步骤
  5. 【LeetCode笔记】621. 任务调度器(Java、桶)
  6. Linux CentOS 编译LUA。。搞半天终于对了= =
  7. 计算机学校招生分数线,重庆工商计算机学校2020年招生录取分数线
  8. linux读取扇区内容,linux-device-driver
  9. PostgreSQL on Docker部署是的shm配置注意
  10. 2018注册测绘师各地报名时间和注意事项!莫错过哦!
  11. 32位win10服务器系统,微软将停止支持32位Win10系统 32位Win10系统什么时候停止支持...
  12. 高效能管理之要事第一 时间管理表格2
  13. win10无法修改mac地址_电脑MAC地址(物理地址)修改方法
  14. 什么是大数据与智能数据?什么是惯性测量单元与GNSS?
  15. 2022年安全员-C证上岗证题目及在线模拟考试
  16. 有哪些计算机语言可以爬虫,爬虫是干嘛的?用什么语言学爬虫好?
  17. 【86】ASPM进入和退出L1
  18. python界面实现点餐系统_基于PythonFlask的网上点餐系统管理员后台开发
  19. Linux操作系统练习之grep,管道,cut 和for循环
  20. Oracle数据增删改查基本命令

热门文章

  1. SQL注入分类、防御
  2. kernel panic - not syncing : fatal exception
  3. 苹果保修期查询_查询iPhone的保修日期和激活日期
  4. 仿射密码加密解密实现
  5. 安卓UTC与时间日期互转方法
  6. Learning Memory-guided Normality for Anomaly Detection 代码解析
  7. Ajax实现跨域请求
  8. XJOI 3679 一道有趣的题 求解求解
  9. 两个hc05蓝牙模块在两块单片机上通信(附完整代码)
  10. 查看表空间已使用和剩余空间大小