c ++ 11中未使用的参数

时间:2013-04-02 12:18:18

标签: c++ c++11 unused-variables

在c ++ 03及更早版本中禁用有关未使用参数的编译器警告我通常使用这样的代码:

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

例如

int main(int argc, char *argv[])
{
    UNUSED(argc);
    UNUSED(argv);

    return 0;
}

但是宏不是c ++的最佳实践,所以。 c ++ 11标准是否有更好的解决方案?我的意思是我可以摆脱宏吗?

谢谢大家!

12 个答案:

答案 0 :(得分:184)

您可以省略参数名称:

int main(int, char *[])
{

    return 0;
}

在main的情况下,你甚至可以完全省略参数:

int main()
{
    // no return implies return 0;
}

参见C ++ 11标准中的“§3.6开始和终止”。

答案 1 :(得分:41)

C ++ 11 中有<tuple>,其中包含即用型std::ignore对象,允许我们编写(非常可能不会强加运行时开销) :

void f(int x)
{
    std::ignore = x;
}

答案 2 :(得分:39)

为此,我使用了一个空体的函数:

template <typename T>
void ignore(T &&)
{ }

void f(int a, int b)
{
  ignore(a);
  ignore(b);
  return;
}

我希望任何认真的编译器能够优化函数调用,并为我静音警告。

答案 3 :(得分:30)

没有什么等同的,没有。

所以你坚持使用相同的旧选项。您是否乐意完全省略参数列表中的名称?

int main(int, char**)

当然,在main的特定情况下,您可以简单地省略参数:

int main()

还有一些典型的特定于实现的技巧,例如GCC的__attribute__((unused))

答案 4 :(得分:26)

要“禁用”此警告,最好是避免编写参数,只需写入类型。

void function( int, int )
{
}

或者如果您愿意,请将其评论出来:

void function( int /*a*/, int /*b*/ )
{
}

您可以混合命名和未命名的参数:

void function( int a, int /*b*/ )
{
}

使用 C ++ 17 ,你有[[maybe_unused]]属性说明符,如:

void function( [[maybe_unused]] int a, [[maybe_unused]] int b )
{
}

答案 5 :(得分:14)

宏可能并不理想,但它们可以很好地满足这一特定目的。我会说坚持使用宏。

答案 6 :(得分:13)

你对旧的标准方式有什么看法?

void f(int a, int b)
{
  (void)a;
  (void)b;
  return;
}

答案 7 :(得分:12)

没有什么新的可用。

最适合我的是在实现中注释掉参数名称。这样,你就可以摆脱警告,但仍保留一些参数的概念(因为名称可用)。

你的宏(以及其他所有的转换为无效的方法)都有缺点,你可以在使用宏后实际使用该参数。这可能会使代码难以维护。

答案 8 :(得分:11)

Boost标头<boost/core/ignore_unused.hpp>(Boost&gt; = 1.56)为此目的定义了函数模板boost::ignore_unused()

int fun(int foo, int bar)
{
  boost::ignore_unused(bar);
#ifdef ENABLE_DEBUG_OUTPUT
  if (foo < bar)
    std::cerr << "warning! foo < bar";
#endif

  return foo + 2;
}

PS C ++ 17具有[[maybe_unused]]属性来抑制未使用实体的警告。

答案 9 :(得分:0)

我真的很喜欢使用宏,因为它允许你在有不同的调试版本时更好地控制(例如,如果你想在启用断言的情况下构建):

#if defined(ENABLE_ASSERTS)
  #define MY_ASSERT(x) assert(x)
#else
  #define MY_ASSERT(x)
#end

#define MY_UNUSED(x)

#if defined(ENABLE_ASSERTS)
  #define MY_USED_FOR_ASSERTS(x) x
#else
  #define MY_USED_FOR_ASSERTS(x) MY_UNUSED(x)
#end

然后像:

一样使用它
int myFunc(int myInt, float MY_USED_FOR_ASSERTS(myFloat), char MY_UNUSED(myChar))
{
  MY_ASSERT(myChar < 12.0f);
  return myInt;
}

答案 10 :(得分:0)

我有自己的时间关键代码段实现。 我一直在研究一段时间关键的减速代码,并且发现这个实现比我优化的时间关键代码消耗了大约2%:

#define UTILITY_UNUSED(exp) (void)(exp)
#define UTILITY_UNUSED2(e0, e1) UTILITY_UNUSED(e0); UTILITY_UNUSED(e1)
#define ASSERT_EQ(v1, v2) { UTILITY_UNUSED2(v1, v2); } (void)0

时间关键代码已将ASSERT*定义用于调试目的,但在发布中它显然已经删除了,但是......似乎这个代码在Visual Studio 2015 Update 3中产生了更快的代码:

#define UTILITY_UNUSED(exp) (void)(false ? (false ? ((void)(exp)) : (void)0) : (void)0)
#define UTILITY_UNUSED2(e0, e1) (void)(false ? (false ? ((void)(e0), (void)(e1)) : (void)0) : (void)0)

原因是双false ?表达式。它以某种方式在发布时以最大优化产生更快的代码。

我不知道为什么这会更快(似乎是编译器优化中的一个错误),但它至少是针对该代码情况的更好解决方案。

注意:   最重要的是,时间关键代码在发布时减慢了没有上面的断言或未使用的宏。换句话说,双false ?表达式令人惊讶地有助于优化代码。

答案 11 :(得分:-1)

windows.h 定义 UNREFERENCED_PARAMETER

#define UNREFERENCED_PARAMETER(P) {(P) = (P);}

所以你可以这样做:

#include <windows.h>
#include <stdio.h>
int main(int argc, char **argv) {
  UNREFERENCED_PARAMETER(argc);
  puts(argv[1]);
  return 0;
}

或Windows之外:

#include <stdio.h>
#define UNREFERENCED_PARAMETER(P) {(P) = (P);}
int main(int argc, char **argv) {
  UNREFERENCED_PARAMETER(argc);
  puts(argv[1]);
  return 0;
}