gpt4 book ai didi

c++ - 使用 constexpr 进行全局和局部变量初始化的区别背后的基本原理

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:04:58 24 4
gpt4 key购买 nike

假设我有一个 constexpr 函数:

constexpr int func() { return 42; }

现在,如果我定义一个用 func() 初始化的全局变量,那么可以保证 func() 将在编译时求值,因为变量需要静态初始化:

int a = func(); // here, func() will be compile-time evaluated
// note that a is NOT constexpr

但是,如果我在函数中初始化局部变量,则不能保证 func() 将在编译时求值:

int foo() {
int b = func(); // no guarantee that func() will be compile-time evaluated
return b;
}

我明白,如果我使用 constexpr int b = func();,那么它将在编译时进行评估。但是,这使得 b const。如果我想在之后修改 b 怎么办?

为什么这两种情况有区别?

最佳答案

一旦将 b 放入堆栈,您就可以修改它,除非您使用 int b const = foo ();。将这样的函数标记为 constexpr 而不是 const 没有任何好处。对于现代 CPU 上的大多数用途,constexpr 是一种减少启动时间的方法,这对于处理器和内存较慢的智能手机来说更为重要。

对于嵌入式系统,我们使用 constexpr 来更容易地将东西放入 ROM。另一种方法是创建一个脚本,为您打印出 C/C++ 代码,但这是一个额外的步骤。你不会在 PC/服务器/智能手机上考虑这个,因为你使用 new 创建动态内存,但你不能在大多数嵌入式系统上这样做(但随着更多的 RAM 和微 Controller 上的 ROM),但是对于嵌入式系统,你有不同类型的内存,你需要将东西放在 RAM 或 ROM 中。这就是上下文是天赐之物的地方,在高性能计算中也是如此,但编译器在 const int foo () { return 420; 之间没有区别。 }constexpr foo () { return 420; },它们都被替换为单个移动指令,而无需运行 O2 优化器。

到目前为止,我最喜欢在嵌入式系统中使用 constexpr 来确保在 ROM 中只有一个远程过程调用 (RPC) header 的拷贝。另一种方法是使用字符串,它最终可能会或可能不会被复制。 constexpr 允许您使用可变参数模板创建非 int 类型的数组,这在历史上一直非常繁琐,需要多个步骤。

C++ 优化的黄金法则是不要试图用其他人在 15 年前教给您的非常有效的更快方法来欺骗编译器。相反,您应该指示编译器您希望它做什么,打开 O2 优化,优化编译器将放弃您的代码并将其替换为针对该 CPU 优化的版本 #LikeABoss。不要像我一样,使用指针算法来设计一个庞大的套接字 API,并浪费数百小时的手动优化代码,而 O2 优化器会来删除你引以为豪的所有漂亮的、有时更好优化的代码。

关于c++ - 使用 constexpr 进行全局和局部变量初始化的区别背后的基本原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52131851/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com