std :: ignore用于忽略未使用的变量

时间:2016-09-28 11:12:21

标签: c++ function c++11 c++14 principles

使用std::ignore忽略未使用的变量是一种好方法吗?

假设我有这样的功能:

void func(int i)
{
   //for some reason, I don't need i anymore but I cannot change signature of function    
   std::ignore = i; 
}

其他信息

这是一个例子,一些答案建议使用匿名变量。但是我如何为其他情况做这件事,比如:

int Thread_UnSafe_func_returnSomething():
void func()
{
   // To make it thread safe
   // Also it is required to call only once
   static int i = Thread_UnSafe_func_returnSomething();

   std::ignore = i;
}

7 个答案:

答案 0 :(得分:40)

在这种情况下,不要写变量名:

void func(int /*i*/)
{
    ...
}

@ Hayt的答案很好,但使用的C ++版本并不总是可用的。不写变量名是一个古老的约定,告诉编译器你实际上并不需要变量。

对于更新的问题,我会选择构造函数中需要初始化的类的静态实例。我说初始化是因为我可以创建这样的函数的唯一原因是初始化一些全局对象。

class SomethingInitializer {
public:
    SomethingInitializer() {
        func_returnSomething();
    }
    ~SomethingInitializer() {
        // Note, that when you initialize something it is a good practice to deinitialize it at the end, and here is a proper place for that.
    }
};

void func() {
    static SomethingInitializer initializer;
}

此解决方案有一个小小的奖励:SomethingInitializer符合RAII标准。因此,当应用程序终止时,析构析构函数被调用,并且可以进行取消初始化。

注意,编译器知道类可以在构造函数和析构函数中做一些有用的事情,所以它不会抱怨未使用的变量。

答案 1 :(得分:37)

std::ignore可能有效,但它可用于元组。所以你需要包含元组头,谁知道为赋值做了哪些操作。这也可能在另一个c ++版本中破坏,因为它从未被记录为以这种方式使用。

更好的方法是C ++ 17属性[[maybe_unused]]

void func([[maybe_unused]] int i)
{
}

它将声明置于变量声明中,因此您不必在额外的行/语句中声明它。

同样可以用于本地(和本地静态)变量

...
[[maybe_unused]] static int a = something();
...

还有更多:

  

出现在类的声明,typedef,变量,a中   非静态数据成员,函数,枚举或枚举器。   如果编译器对未使用的实体发出警告,则表示该警告   被压缩为任何声明为maybe_unused的实体。

请参阅http://en.cppreference.com/w/cpp/language/attributes

对于有关人员,在声明未使用变量后仍可使用变量:

是的,这是可能的,但(至少对于clang)如果您使用maybe_unused声明的变量,您将收到警告。

答案 2 :(得分:15)

std::ignore并非旨在用于此目的:

  

未指定类型的对象,以便可以为其分配任何值而不起作用。在解压缩std :: tuple时用于std :: tie,作为未使用的参数的占位符。

我建议你做你正在考虑的事情,因为在一个真实的大项目中,它会导致代码更难维护,人们会看到原型函数,会看到它需要一个参数int i,但实际上这个函数不需要它 - 感觉不好,是吗? :)

答案 3 :(得分:8)

作为替代方案,如果不从签名中删除i(因为某些文档工具可能需要它),有几种方法可以使警告静音:

void func(int i)
{
   static_cast<void>(i); // Silent warning for unused variable
}

它不是完全可移植的,但是大多数编译器都会发出警告。

干净的方法是为此创建一个专用函数:

template <typename T>
void Unused(T&& /*No name*/) { /*Empty*/ }

然后

void func(int i)
{
   Unused(i); // Silent warning for unused variable
}

答案 4 :(得分:2)

我认为你有一个XY问题。你真的不关心如何忽略静态变量;你只想以线程安全,可重入的方式调用一次函数(并且只调用一次)。

我说:你听说过std::call_once吗?您应该将方法重写为

#include <mutex>

int Thread_UnSafe_func_returnSomething();
void func(void)
{
      //To make it thread safe
     static std::once_flag initComplete;
     std::call_once(initComplete, func_returnSomething);
 }

答案 5 :(得分:1)

另一种方法是使用尾随返回类型,如下所示:

auto func(int i) -> decltype(void(i)) {}
int main() {}

如果您有多个变量,可以全部列出:

auto func(int i, int j) -> decltype(void(i), void(j)) {}
int main() {}

如果void不符合您的要求,您仍然可以声明您的首选回复类型:

auto func(int i) -> decltype(void(i), int{}) { return 42; }
int main() {}

此解决方案的优点是:

  • 保留变量名:如其他人所述,不要给变量命名,也不能作为选项(因为你的文档系统,作为一个例子)。

  • 你不会用无用的表达方式污染你的功能体,旨在沉默一些警告。

  • 您不必明确定义支持功能即可。

当然,这不适用于函数体中声明的静态变量,但是从函数返回时可以做类似的事情(只是一个例子):

int f() {
    static int i = 0;
    static int j = 0;
    return void(i), void(j), 42;
}

int main () {}

更多的原则不那么相同。

答案 6 :(得分:0)

我想为那些使用 ARM 编译的人推荐一个替代方案。

您可以使用 _attribute_ keyword"unused" attribute 分配给变量。这样做会导致编译器在未引用变量的情况下不生成任何警告。

您可以将“未使用”属性分配给方法声明中的方法参数。只需将属性关键字与“未使用”属性一起放在变量名称之后即可。我在下面提供了一个例子。

示例:

void someFunc(int x __attribute__((unused)) );

文档可以参考here.