在 C++ 中,表达式是有效的语句;计算出的值被简单地丢弃。
有些编译器足够聪明,如果代码看起来很奇怪,它们会发出警告;例如有:
foo(1,2,3);
可以有意义(调用可能有副作用的函数)但代码如下
x < 3;
没有用,因为它没有定义的副作用并且该值被丢弃。
在 g++ 中,还有一些库函数,尽管有副作用,但仍被专门标记,以便忽略返回值会引发警告(例如fread
)因为这是虫子等待咬人的迹象。
还有一些非常常见的情况,经常会忽略函数的结果(例如printf
)并且其中返回值的表达式仅用于副作用(例如std::cout << "Hello";
).
如果您想在运行时强制执行函数的结果不会被默默忽略,有时可以使用一个技巧:
template<typename T>
struct must_check {
T x;
bool checked;
must_check(const T& x) : x(x), checked(false) {}
operator T () { checked = true; return x; }
~must_check() {
if (!checked)
throw std::runtime_error("Result value has not been checked");
}
};
现在而不是写
int square(int x) {
return x * x;
}
写吧
must_check<int> square(int x) {
return x * x;
}
然后代码如下
square(12);
会在运行时抛出异常,而
int result = square(12);
会工作得很好。
这是可能的,但并不是一个真正的好主意,因为在析构函数中抛出异常是一种非常糟糕的行为,通常会导致程序异常终止(原因是有时由于异常而自动调用析构函数,抛出异常)another该阶段的异常是致命的举动)。
UPDATE
C++17 引入了一个注释,以便丢弃可疑的返回值可以在编译时发出警告。例如代码
[[nodiscard]] double square(double x) {
return x*x;
}
如果不使用返回值,将在编译时触发警告。