C++ 如何最好地消除有关未使用变量的警告?

C++ 如何最好地消除有关未使用变量的警告?,c++,gcc,warnings,gcc-warning,C++,Gcc,Warnings,Gcc Warning,我有一个跨平台的应用程序,在我的一些功能中,没有使用传递给功能的所有值。因此,我从GCC得到一个警告,告诉我存在未使用的变量 围绕警告进行编码的最佳方式是什么 函数周围的#ifdef #ifdef _MSC_VER void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal qrLeft, qreal qrTop, qreal qrWidth, qreal qrHeight) #else void

我有一个跨平台的应用程序,在我的一些功能中,没有使用传递给功能的所有值。因此,我从GCC得到一个警告,告诉我存在未使用的变量

围绕警告进行编码的最佳方式是什么

函数周围的#ifdef

#ifdef _MSC_VER
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal qrLeft, qreal qrTop, qreal qrWidth, qreal qrHeight)
#else
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal /*qrLeft*/, qreal /*qrTop*/, qreal /*qrWidth*/, qreal /*qrHeight*/)
#endif
{
这很难看,但似乎是编译器更喜欢的方式

还是将零赋给函数末尾的变量?(我讨厌它,因为它改变了程序流中的某些内容,使编译器警告静音)

有正确的方法吗?

您可以(不做任何事情)让编译器看到它被使用。这在编译器之间是可移植的

例如

或者


总是注释掉参数名不安全吗?如果不是这样,你可以做类似的事情

#ifdef _MSC_VER
# define P_(n) n
#else
# define P_(n)
#endif

void ProcessOps::sendToExternalApp(
    QString sAppName, QString sImagePath,
    qreal P_(qrLeft), qreal P_(qrTop), qreal P_(qrWidth), qreal P_(qrHeight))

它没有那么难看。

我看不出你的警告有什么问题。在方法/函数标题中记录编译器xy将在此处发出(正确的)警告,但平台z需要这些变量


警告正确,无需关闭。它不会使程序失效-但应该记录下来,这是有原因的。

您当前的解决方案是最好的-如果您不使用它,请注释掉参数名称。这适用于所有编译器,因此您不必专门为GCC使用预处理器。大多数情况下,使用预处理器指令被认为是有害的。理想情况下,你要像避开害虫一样避开它们。请记住,让编译器理解您的代码很容易,让其他程序员理解您的代码要困难得多。在这里和那里有几十个这样的案例,这使得你很难在以后或现在为别人阅读

一种方法可能是将参数组合到某种参数类中。然后,您可以只使用变量的一个子集(相当于实际分配0),或者为每个平台使用该参数类的不同专门化。然而,这可能不值得,您需要分析它是否合适


如果您能阅读不可能的模板,您可能会在“Exception C++”一书中找到高级技巧。如果那些阅读你的代码的人能够掌握他们的技能,把书中教给你的那些疯狂的东西都包含进去,那么你就会拥有漂亮的代码,这些代码也很容易阅读。编译器也会很清楚您正在做什么(而不是通过预处理隐藏一切)

在GCC和Clang中,您可以使用
\uuuu属性(未使用))
预处理器指令来实现您的目标。
例如:

int foo (__attribute__((unused)) int bar) {
   return 0;
}

使用
未引用的_参数(p)
可以工作。我知道它是在WinNT.h中为Windows系统定义的,也可以很容易地为gcc定义(如果它还没有的话)

未引用参数(p)
定义为

#define UNREFERENCED_PARAMETER(P)          (P)

在WinNT.h.

中,首先警告是由源文件中的变量定义而不是头文件生成的。头部可以保持原始状态,并且应该保持原始状态,因为您可能正在使用类似于doxygen的东西来生成API文档

我假设您在源文件中有完全不同的实现。在这些情况下,您可以注释掉有问题的参数,也可以只编写参数

例如:

func(int a, int b)
{
    b;
    foo(a);
}
 [[maybe_unused]] void f([[maybe_unused]] bool thing1,
                        [[maybe_unused]] bool thing2) {
  [[maybe_unused]] bool b = thing1 && thing2;
    assert(b);
 }
这可能看起来很神秘,所以定义了一个类似UNUSED的宏。MFC的做法是:

#ifdef _DEBUG
#define UNUSED(x)
#else
#define UNUSED(x) x
#endif

像这样,您在调试版本中仍然可以看到警告,这可能会有所帮助。

一位同事刚刚向我指出了这个漂亮的小宏

为了方便起见,我将包括下面的宏

#ifdef UNUSED
#elif defined(__GNUC__) 
# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) 
#elif defined(__LCLINT__) 
# define UNUSED(x) /*@unused@*/ x 
#else 
# define UNUSED(x) x 
#endif

void dcc_mon_siginfo_handler(int UNUSED(whatsig))

更简洁的方法是只注释掉变量名:

int main(int /* argc */, char const** /* argv */) {
  return 0;
}
默认情况下不标记这些警告。必须通过将
-Wunused参数
显式传递给编译器或通过传递
-Wall-Wextra
隐式传递(或可能是其他一些标志组合)来打开此警告

通过将
-Wno Unused parameter
传递给编译器,可以简单地抑制未使用的参数警告,但请注意,此禁用标志必须位于编译器命令行中此警告的任何可能的启用标志之后,才能生效。

C++17 Update 在C++17中,我们获得属性[[maybe_unused]],该属性在

属性标记maybe_unused表示可能有意未使用名称或实体。它应该 在每个属性列表中最多出现一次,且不应出现属性参数子句。

例如:

func(int a, int b)
{
    b;
    foo(a);
}
 [[maybe_unused]] void f([[maybe_unused]] bool thing1,
                        [[maybe_unused]] bool thing2) {
  [[maybe_unused]] bool b = thing1 && thing2;
    assert(b);
 }
无论是否定义了NDEBUG,实现都不应该警告b未使用-[结束示例]

对于以下示例:

int foo ( int bar) {
    bool unused_bool ;
    return 0;
}
int foo (int bar) {
    UNUSED(bar) ;
    return 0;
}
clang和gcc都使用-Wall-Wextra条形图和未使用的布尔图生成诊断

添加[[maybe_unused]]会使诊断静音:

int foo ([[maybe_unused]] int bar) {
    [[maybe_unused]] bool unused_bool ;
    return 0;
}

在C++17之前 在C++11中,
UNUSED
宏的另一种形式可以使用lambda表达式()和未使用变量的捕获来形成:

#define UNUSED(x) [&x]{}()
鉴于以下示例,应优化lambda表达式的即时调用:

int foo ( int bar) {
    bool unused_bool ;
    return 0;
}
int foo (int bar) {
    UNUSED(bar) ;
    return 0;
}
我们可以看到,调用被优化了:

foo(int):
xorl    %eax, %eax
ret

您可以使用
\uuu unused
告诉编译器可能不使用该变量

- (void)myMethod:(__unused NSObject *)theObject    
{
    // there will be no warning about `theObject`, because you wrote `__unused`

    __unused int theInt = 0;
    // there will be no warning, but you are still able to use `theInt` in the future
}

无宏且可移植的将一个或多个
参数声明为未使用的方式:

template <typename... Args> inline void unused(Args&&...) {}

int main(int argc, char* argv[])
{
    unused(argc, argv);
    return 0;
}
template inline void unused(Args&&…{}
int main(int argc,char*argv[])
{
未使用(argc、argv);
返回0;
}

使用编译器的标志,例如GCC的标志:
-Wno未使用的变量

这很有效,但需要C++11

template <typename ...Args>
void unused(Args&& ...args)
{
  (void)(sizeof...(args));
}
模板
无效未使用(Args&…Args)
{
(无效)(sizeof…(args));
}

C++17现在提供了
[[maybe\u unused]]
属性


非常好而且标准。

我发现大多数给出的答案都适用于
template<typename... Ts> inline void Unreferenced(Ts&&...) {}

int Foo(int bar) 
{
    Unreferenced(bar);
    return 0;
}

int Foo2(int bar1, int bar2) 
{
    Unreferenced(bar1, bar2);
    return 0;
}
(decltype(Unreferenced(bar1, bar2)))0;
#define UNREFERENCED(...) { (decltype(Unreferenced(__VA_ARGS__)))0; }
void foo(int param1, int param2)
{
    std::ignore = param2;
    bar(param1);
}