关于cout运行时机、函数重复打印及全局调用合法性的技术疑问
问题解答
代码示例
import std; constexpr void logError(const std::string& error); constexpr int sqrt(int x) { if (x < 0) { logError("Oh no, this can't be real..."); return -1; } else { int result{ 1 }; while (result * result <= x) ++result; return result - 1; } } int c = sqrt(-1); int main() { sqrt(-1); } constexpr void logError(const std::string& error) { if (!std::is_constant_evaluated()) std::cout << error << std::endl; }
为什么会打印两次信息?
- 代码里有两处
sqrt(-1)调用:一处是全局变量c的初始化语句int c = sqrt(-1);,另一处是main函数内的sqrt(-1);。 - 全局变量的初始化属于程序运行时启动阶段,并非编译期常量求值。此时
logError中!std::is_constant_evaluated()判断为真,会执行cout输出信息。 main函数内的调用同样是运行时执行,再次触发cout输出。两处调用各自触发一次打印,所以最终输出两次。
int c = sqrt(-1);调用logError是否合法?
- 完全合法。
sqrt是constexpr函数,但这仅表示它可以在常量求值上下文执行,而非必须。当用于普通全局变量(非constexpr)的初始化时,编译器会选择在运行时执行该函数,而非编译期。- 运行时执行时,
logError中的IO操作符合C++标准,没有问题。如果将c声明为constexpr int c = sqrt(-1);,此时进入常量求值流程,std::is_constant_evaluated()返回true,!后为false,cout不会执行,也不会触发常量求值中禁止IO的规则。
内容的提问来源于stack exchange,提问作者ntos
相关产品推荐
相关产品推荐

