86

在 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标准有没有更好的解决方案?我的意思是我可以摆脱宏吗?

谢谢大家!

4

12 回答 12

212

您可以省略参数名称:

int main(int, char *[])
{

    return 0;
}

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

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

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

于 2013-04-02T12:19:26.373 回答
56

<tuple>C++11中有一个,其中包括准备使用std::ignore的对象,它允许我们编写(很可能不会产生运行时开销):

void f(int x)
{
    std::ignore = x;
}
于 2013-05-27T07:59:48.100 回答
45

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

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

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

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

于 2013-04-02T12:55:23.637 回答
38

要“禁用”这个警告,最好避免写参数,只写类型。

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 )
{
}
于 2013-04-03T11:41:10.970 回答
29

没有什么等价的,不。

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

int main(int, char**)

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

int main()

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

于 2013-04-02T12:20:12.473 回答
14

宏可能并不理想,但它们在这个特定目的上做得很好。我会说坚持使用宏。

于 2013-04-02T12:24:23.867 回答
14

你有什么反对旧的和标准的方式?

void f(int a, int b)
{
  (void)a;
  (void)b;
  return;
}
于 2013-04-02T18:11:48.960 回答
13

Boost 标头<boost/core/ignore_unused.hpp>(Boost >= 1.56) 为此目的定义了函数 template 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]]抑制未使用实体的警告的属性。

于 2014-06-19T15:47:37.870 回答
11

没有什么新东西可用。

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

您的宏(以及所有其他强制转换为 void 的方法)的缺点是您可以在使用宏后实际使用该参数。这会使代码更难维护。

于 2013-04-02T12:29:14.783 回答
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;
}
于 2016-06-21T10:39:03.390 回答
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 ?表达式出人意料地有助于优化代码。

于 2017-10-19T18:20:51.490 回答
-2

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;
}
于 2016-02-04T04:52:42.950 回答