C++:弃值表达式

正文

有时候需要利用某些表达式的副作用来实现某些目的:

1
2
3
4
5
6
7
8
9
10
#include <iostream>
template <typename... Args>
void print(const Args &...args) {
Arr{0,(std::cout << args<< ' ',0)...};
}
int main() {
print("hello", 1, 2, 3, 4, 5, 6);
print();
return 0;
}

但这会产生警告:

1
2
3
4
5
6
7
8
9
10
11
12
13
multi2.cxx:7:5: warning: expression result unused [-Wunused-value]
Arr{0,(std::cout << args<< ' ',0)...};
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
multi2.cxx:10:5: note: in instantiation of function template specialization 'print<char [6], int, int, int, int, int, int>' requested here
print("hello", 1, 2, 3, 4, 5, 6);
^
multi2.cxx:7:5: warning: expression result unused [-Wunused-value]
Arr{0,(std::cout << args<< ' ',0)...};
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
multi2.cxx:11:5: note: in instantiation of function template specialization 'print<>' requested here
print();
^
2 warnings generated.

为了消除警告,可以用关键字 void明确表示这是一个弃值表达式,即:

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
template <typename... Args>
void print(const Args &...args) {
using Arr = int[];
(void)Arr{0,(std::cout << args<< ' ',0)...};
}
int main() {
print("hello", 1, 2, 3, 4, 5, 6);
print();
return 0;
}

关于 void 表明弃值表达式的使用,实际上并非 void 本身表示弃值表达式,而是在某些上下文中使用 void 来表明该表达式的返回值被丢弃。例如,在函数声明中,如果函数的返回类型是 void,那么调用该函数就意味着对返回值的忽略,从而可以被视为一种弃值操作。

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
int getValue() {
std::cout << "Getting value..." << std::endl;
return 42;
}

int main() {

(void)getValue();
// 使用弃值表达式,利用副作用
int x = 10;
(void)((x > 5) ? (std::cout << "hello1\n", 0)
: (std::cout << "hello2\n", 0));

return 0;
}

上面的 getValue()确实有一个返回值,但是我们调用它的时候并不需要这个返回值,因此可以用关键字 void 表明我们放弃了这个值,并告诉编译器不要产生警告。另外,根据条件 x > 5 的结果,选择输出 “hello1” 还是 “hello2”。无论选择哪个分支,最终都返回 0,这个返回值在这里被忽略,只关注分支执行时的副作用(输出文本)。


C++:弃值表达式
http://blog.luliang.online/2024/04/11/C++:弃值表达式/
作者
Luyoung
发布于
2024年4月11日
许可协议