我有一个跨平台的应用程序,在我的几个函数中,并不是所有传递给函数的值都被利用。因此我从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
{

这是如此丑陋,但似乎是编译器更喜欢的方式。

还是把函数末尾的变量赋值为0 ?(我讨厌这样做,因为它改变了程序流中的某些东西,从而使编译器警告静音)。

有正确的方法吗?


当前回答

这工作得很好,但需要c++ 11

template <typename ...Args>
void unused(Args&& ...args)
{
  (void)(sizeof...(args));
}

其他回答

一个同事刚给我指了这个小宏

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

#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))

你可以把它放在"(void)var;"表达式中(什么都不做),这样编译器就可以看到它被使用了。这在编译器之间是可移植的。

E.g.

void foo(int param1, int param2)
{
    (void)param2;
    bar(param1);
}

Or,

#define UNUSED(expr) do { (void)(expr); } while (0)
...

void foo(int param1, int param2)
{
    UNUSED(param2);
    bar(param1);
}

默认情况下,GCC不会标记这些警告。此警告必须通过显式地向编译器传递-Wunused-parameter或隐式地传递-Wall -Wextra(或其他一些标志的组合)来开启。

未使用的参数警告可以通过向编译器传递-Wno-unused-parameter来抑制,但请注意,这个禁用标志必须出现在编译器命令行中任何可能的用于此警告的启用标志之后,这样它才能生效。

c++ 17更新

在c++ 17中,我们获得了[[maybe_unused]]属性,该属性包含在[dcl.attr.unused]中。

属性令牌maybe_unused表示一个名称或实体可能是故意未使用的。应当 每个属性列表中最多出现一次,且不允许出现属性参数子句。 ... 例子: [[maybe_unused]] void f([[maybe_unused]] bool thing1, [[maybe_unused]] bool thing2 { [[maybe_unused]] bool b = thing1 && thing2; 断言(b); } 不管是否定义了NDEBUG,实现都不应该警告b未使用。-end示例]

示例如下:

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

clang和gcc都使用-Wall -Wextra为bar和unused_bool生成诊断。

添加[[maybe_unused]]将使诊断静默:

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

现场观看。

在c++ 17

在c++ 11中,可以使用lambda表达式(通过Ben Deane)捕获未使用的变量来形成UNUSED宏的另一种形式:

#define UNUSED(x) [&x]{}()

lambda表达式的直接调用应该被优化掉,给出如下示例:

int foo (int bar) {
    UNUSED(bar) ;
    return 0;
}

我们可以在godbolt中看到调用被优化了:

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

总是注释掉参数名是否不安全?如果不是,你可以做一些

#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))

它不那么难看。