繁体   English   中英

c ++ 11中未使用的参数

[英]Unused parameter in c++11

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

谢谢大家!

您可以省略参数名称:

int main(int, char *[])
{

    return 0;
}

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

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

请参阅C ++ 11标准中的“第3.6节”启动和终止“。

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

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

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

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

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

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

什么都没有,没有。

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

int main(int, char**)

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

int main()

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

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

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 )
{
}

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

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

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

没有什么新的可用。

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

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

为此,Boost头<boost/core/ignore_unused.hpp> (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;
}

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

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

#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;
}

我有自己的时间关键代码段实现。 我一直在研究一段时间关键的减速代码,并且发现这个实现从我优化的关键代码中消耗了大约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 ? 表达式令人惊讶地有助于优化代码。

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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM