C++17新增了3个属性: [[fallthrough]]
, [[nodiscard]]
和 [[maybe_unused]]
。
看一个快速的例子:
-
#include <cassert>
-
// 如果 foo() 返回值被忽略不用编译器会警告
-
[[nodiscard]] int foo();
-
int main() {
-
int a {1};
-
switch (a) {
-
// 指明case 1会掉下去
-
case 1: [[fallthrough]]
-
case 2:
-
// 指明b 可能没用上,例如release build中
-
[[maybe_unused]] int b = foo();
-
assert(b > 0);
-
break;
-
}
-
}
[[fallthrough]]
C++17之前的标准下,有如下代码:
-
switch (device.status())
-
{
-
case sleep:
-
device.wake();
-
// fall thru
-
case ready:
-
device.run();
-
break;
-
case bad:
-
handle_error();
-
break;
-
}
在C++17时可以这样写:
-
switch (device.status())
-
{
-
case sleep:
-
device.wake();
-
[[fallthrough]];
-
case ready:
-
device.run();
-
break;
-
case bad:
-
handle_error();
-
break;
-
}
区别就是新增的 [[fallthrough]]
属性。如果这里不写 [[fallthrough]]
,编译也是能通过的,但会报诸如 warning: case statement without break
之类的警告。C++中 switch-case
默认是会继续往下走,有的时候程序员可能因为粗心会漏写 break
,就会导致非预期的运行逻辑,有的语言比如Go则默认会跳出当前 case
,C++17中新增 [[fallthrough]]
属性可以多一次机会提醒程序员仔细思考这里正常逻辑应该是怎样的。
[[nodiscard]]
C++17之前的标准下,有如下代码:
-
struct SomeInts
-
{
-
bool empty();
-
void push_back(int);
-
//etc
-
};
-
void random_fill(SomeInts & container,
-
int min, int max, int count)
-
{
-
container.empty(); // empty it first
-
for (int num : gen_rand(min, max, count))
-
container.push_back(num);
-
}
在C++17时可以这样写:
-
struct SomeInts
-
{
-
[[nodiscard]] bool empty();
-
void push_back(int);
-
//etc
-
};
-
void random_fill(SomeInts & container,
-
int min, int max, int count)
-
{
-
container.empty(); // empty it first
-
for (int num : gen_rand(min, max, count))
-
container.push_back(num);
-
}
加上 [[nodiscard]]
后,编译器发现 empty()
函数被调用时并没有使用它的返回值,则会报一个诸如 warning: ignoring return value of 'bool empty()'
的警告。
除了可以用在函数上,也可以用在类或结构体上,作用是该类或结构体被作为返回值类型时,如果不使用该返回值,则编译器警告。例如:
-
struct [[nodiscard]] MyError {
-
std::string message;
-
int code;
-
};
-
MyError divide(int a, int b) {
-
if (b == 0) {
-
return {"Division by zero", -1};
-
}
-
std::cout << (a / b) << '\n';
-
return {};
-
}
-
divide(1, 2);
报警告 warning: ignoring return value of function declared with 'nodiscard' attribute
。
建议要谨慎考虑是否真的需要使用 [[nodiscard]]
属性,如果确实任何情况下都没理由可以忽略掉返回值,则可以使用。
[[maybe_unused]]
有代码如下:
-
bool res = step1();
-
step2();
-
etc();
编译时可能会报警告说 res变量定义了却没有使用
诸如此类的话。C++17引入了 [[maybe_unused]]
属性,可以修改如下:
-
[[maybe_unused]] bool res = step1();
-
step2();
-
etc();
这样编译器就不会再对 res
变量没有被使用而报警告了。
除了可以修饰变量,此属性也可用于修饰函数,例如:
-
[[maybe_unused]] void f()
-
{
-
/*...*/
-
}
-
int main()
-
{
-
}