c ++ 11中未使用的参数

ink*_*boo 75 c++ c++11 unused-variables

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

#define UNUSED(expr) do { (void)(expr); } while (0)
Run Code Online (Sandbox Code Playgroud)

例如

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

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

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

谢谢大家!

Hen*_*rik 187

您可以省略参数名称:

int main(int, char *[])
{

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

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

int main()
{
    // no return implies return 0;
}
Run Code Online (Sandbox Code Playgroud)

请参阅C++ 11标准中的"第3.6节"启动和终止".

  • 这对我来说似乎是最好的答案 - 任何使用宏或模板的东西仍然不能确保变量不能在之后使用.这两者都会使警告静音_和_确保不能使用(未命名)参数. (27认同)
  • 在"main"的情况下,您可以完全省略参数.就此问题而言,"返回"声明. (12认同)
  • @jotep好的,我会咬人的.你为什么认为这是好习惯? (6认同)
  • 我几乎总是在测试用例中省略`main`的`return 0`,但几乎总是在生产代码中编写自我记录的`return EXIT_SUCCESS`._That_的好习惯! (6认同)
  • @MikeSeymour我实际上认为省略return语句是一种好习惯. (4认同)
  • @LightnessRacesinOrbit关于"说同样的事情":这是正确的,我不确定为什么我的答案得到最多的赞成.也许是因为它是第一个.关于"实际解决问题":是的我可以明确说明,"没有新的C++ 11功能",但答案清楚地表明不需要这样的功能(或使用宏)来使警告静音. (2认同)
  • Necro 评论,但您可以随时将其注释掉,而不是忽略它们。它需要另外四个字符,您需要的所有信息仍在源中,没有讨厌的警告。 (2认同)

Ori*_*ent 44

还有就是<tuple>C++ 11,其中包括准备使用std::ignore的对象,这让我们写(很可能不附加任何运行时开销):

void f(int x)
{
    std::ignore = x;
}
Run Code Online (Sandbox Code Playgroud)

  • 考虑到这是在标准库中,因此不需要编写自定义函数我会说这是最好的解决方案! (4认同)
  • 此类“打算在解压缩std :: tuple时与std :: tie一起使用”,而不是针对此用例。我会说这是一个解决方案,但可能不是最好的。 (2认同)

Mad*_*ist 38

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

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

void f(int a, int b)
{
  ignore(a);
  ignore(b);
  return;
}
Run Code Online (Sandbox Code Playgroud)

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

  • -1,这是荒谬的和不必要的装置,特别是当你可以省略参数名称时.坦率地说,令我困扰的是,这有25个赞成票. (25认同)
  • 当`T`是模板参数时,`T &&`是*通用引用*,它绑定到任何东西. (20认同)
  • 为什么忽略内置方法?只需省略参数名称即可. (11认同)
  • +1虽然甚至没有提及*Xeo*的评论中的高级版本. (3认同)
  • @ TC1这使您的代码明确了解它的作用和原因.拥有未使用的参数或变量是代码中的气味,这使它显而易见.关闭警告会使您的代码闻起来更多. (3认同)
  • 取消命名它们,所以函数接受参数,但不将它赋给任何变量:`int main(int/*argc*/,char**/*argv*/)` (2认同)
  • 不要重新发明轮子!使用boost,参见[下面的答案](http://stackoverflow.com/a/24310846/888576) (2认同)

Lig*_*ica 30

什么都没有,没有.

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

int main(int, char**)
Run Code Online (Sandbox Code Playgroud)

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

int main()
Run Code Online (Sandbox Code Playgroud)

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


Nik*_*kko 28

要"禁用"此警告,最好是避免编写参数,只需编写类型即可.

void function( int, int )
{
}
Run Code Online (Sandbox Code Playgroud)

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

void function( int /*a*/, int /*b*/ )
{
}
Run Code Online (Sandbox Code Playgroud)

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

void function( int a, int /*b*/ )
{
}
Run Code Online (Sandbox Code Playgroud)

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

void function( [[maybe_unused]] int a, [[maybe_unused]] int b )
{
}
Run Code Online (Sandbox Code Playgroud)

  • @Wallacoloo当我想要注释掉大块代码时,我使用#if 0 ... #endif,它们被允许嵌套并且永远不会与现有的/*...*/comments冲突. (4认同)
  • 我曾经这样做过,但很快就会变成一种痛苦,因为你不能再用`/*...*/`来注释大块的代码了. (2认同)
  • 这是真的,但我想如果你选择一个块来自动注释,它会在每一行的开头添加一堆“//”。这就是 Eclipse CDT 所做的。就个人而言,我只使用第一个没有名字的例子。(例如,您可以将名称放在 .h 文件的声明中)。 (2认同)

Mat*_*son 14

宏可能不是理想的,但它们为这个特定的目的做得很好.我会说坚持使用宏.

  • +1:在这种情况下,它们会造成零伤害并解决问题.我没有看到任何理由(除了"永远不会使用宏"这个荒谬的毫无根据的口头禅),不要在这里使用它们. (5认同)
  • @MatthieuM.:因为这个原因,我会调用宏`MAYBE_UNUSED`; 我通常不在乎我是否说"不要担心,如果我不使用下面这个",但无论如何继续这样做. (2认同)
  • 好吧,所以正确的事情可能是称之为"HIDE_UNUSED_WARNING".但我仍然认为在这里使用宏是一个非常有效的想法.只要宏以这样的方式命名,即它不会引起混淆和/或与其他代码冲突. (2认同)

jca*_*zac 13

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

void f(int a, int b)
{
  (void)a;
  (void)b;
  return;
}
Run Code Online (Sandbox Code Playgroud)


Rei*_*ica 12

没有什么新的可用.

对我来说最有效的是在实现中注释掉参数名称.这样,您就可以摆脱警告,但仍保留一些参数的概念(因为名称可用).

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


man*_*lio 12

<boost/core/ignore_unused.hpp>为此,Boost标头(Boost> = 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;
}
Run Code Online (Sandbox Code Playgroud)

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