什么时候应该使用[[maybe_unused]]?

47

使用[[maybe_unused]]有哪些好处?请考虑

int winmain(int instance, int /*prevInstance*/, const char */*cmdline*/, int show);

int winmain(int instance, [[maybe_unused]] int prevInstance, [[maybe_unused]] const char *cmdline, int show);
一些人可能会坚持认为使用注释是丑陋的,因为此关键字是为在这些情况下使用而制作和打算的,我完全同意这一点,但 maybe_unused 关键字对我来说有点太长了,使得代码稍微难以阅读。
我想尽可能地遵循标准,但它值得使用吗?

4
如果你有条件地(例如使用宏)排除用于调试目的的变量的代码,那么这是有用的。 - Rakete1111
6
当宏被人为破坏时,不能责怪编译器。 - StoryTeller - Unslander Monica
7
@JesperJuhl这个跟任何事情有什么关系吗?未使用的参数/变量的问题在于它们会产生警告... - bolov
6
警告可以揭示一个 bug,当你本意想使用某个变量时,却错误地使用了另一个变量。 - Jordan Melo
3
@davidbak 5分钟前它在编译时为我捕获了一个错误 :) - Jordan Melo
显示剩余4条评论
4个回答

103
如果参数明确未使用,[[maybe_unused]]并不特别有用,对于这种情况,未命名的参数和注释就可以胜任。 [[maybe_unused]]最有用的是针对那些可能未使用的东西,例如:
void fun(int i, int j) {
    assert(i < j);
    // j not used here anymore
}

这不能使用未命名的参数来处理,但如果定义了NDEBUG,则会产生警告,因为j未使用。

当参数仅用于(可能已禁用的)日志记录时,可能会出现类似情况。


56
谁会想到 maybe_unused 中的 "maybe" 实际上很重要... - bolov

76

Baum mit Augen的回答是权威且无可争议的解释。我只想提供另一个例子,它不需要宏。具体来说,C++17引入了constexpr if结构。因此,您可能会看到像这样的模板代码(除了愚蠢的功能):

#include <type_traits>

template<typename T>
auto add_or_double(T t1, T t2) noexcept {
    if constexpr (std::is_same_v<T, int>)
        return t1 + t2;
    else
        return t1 * 2.0;
}

int main(){
    add_or_double(1, 2);
    add_or_double(1.0, 2.0);
}

截至目前,GCC 8.0.1在else分支被实例化时警告我未使用t2。在这种情况下,该属性也是必不可少的。

15
不错的例子,很好地说明了不仅"恶意"宏可以导致这种情况。 - Baum mit Augen
5
我认为这是一个服务质量问题(QoI) :) - Rakete1111
@Rakete1111,编译器的质量如何? - alfC
1
@alfC 是的,完全正确。 - Rakete1111
1
@GabrielDevillers,看起来是这样。 (请询问Rakete111以确认) - alfC
显示剩余2条评论

1

当您拥有一组常量来定义可能或可能不使用的一组配置常量时,我认为[[maybe_unused]]非常有用。然后您可以自由更改配置而无需定义新的常量并担心未使用的常量。

我主要在嵌入式代码中使用它,其中您必须设置特定值。否则,枚举通常更好。


0

使用它来抑制未使用变量的编译器警告。是否选择使用这种方法取决于您所在团队或组织的编码标准和实践。

在某些工作场所,使用注释掉未使用变量的方法如下:

bool f (auto /*unusedVariable*/) {return false;}

常见做法。它有效地传达了保留变量的意图,即使它看起来没有被使用。
相反,在其他开发环境中,使用宏等技术可能更受青睐,以解决这个问题并使代码库远离此类注释的干扰。
bool f (auto unusedVariable) 
{
   UNUSED (unusedVariable);
   return false;
}

最终,选择这些方法或任何其他方法应该与您特定项目或团队的编码约定和要求保持一致。没有一种适用于所有情况的答案,重要的是在代码库中保持一致性。
以下是一个常见的例子,其中[[maybe_unused]]被广泛接受:
#include <algorithm>
#include <iostream>
#include <vector>
 
int main()
{
   std::vector<int> v {0, 1, 2, 3 };
   
   std::cout << std::count_if (v.begin (), v.end (), [] (int i) {return (i & 1);}) << "\n";
   std::cout << std::count_if (v.begin (), v.end (), [] ([[maybe_unused]] int i) {return true;}) << "\n"; // Compiles without a warning
   std::cout << std::count_if (v.begin (), v.end (), [] (int i) {return false;}) << "\n"; // Produces a warning
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接