迟来总比不来好:我正试图更新我的代码库以适应最新的C++标准,现在正试图真正理解constexpr语法功能的意图。
然而,我正在为这个问题而苦恼。在我的一个单片机项目中(普通的C++,没有一些更高级的标准功能),我有一个... 配置头 包含了大量的#define语句,允许非开发者用户配置某些常量值(大多数时候是与设备相关的参数)。例子:在我看来,这将是一个很好的选择。
#define SERIAL_DEVICE_XY_BAUD_RATE (9600)
#define MAX_SENSORDATA_BUFFER_LENGTH (250)
在我看来,这将是一个很好的选择,可以将其迁移到constexpr定义中(对我来说,最大的问题是这些值的命名空间和类型安全)。
现在我的问题是。当我想保留单独的头文件和配置常量时,如何在不重复分配内存的情况下使用constexpr?根据我的理解,迁移到constexpr,如。
constexpr unsigned int device1_baud_rate = 115200;
会给出一个完全隔离的(新)变量,并分配适当的内存。当在程序中其他地方的类的构造函数中使用这个变量时(就像现在的宏定义一样),它会被复制到成员变量中,使我有两个变量分配而不是一个。
我想我缺少一种直接使用这种constexpr值的概念,有谁能给我指出正确的方向?谢谢
你总是可以使用像 godbolt 这样的工具来查看编译器创建的内容。如果你检查结果为 这套 你会发现,编译器将为你的 #define
和 costexpr
如果你只将它们作为常量使用,即使没有开启优化功能。
#include <iostream>
#define DEFINE_CONST (9600)
constexpr unsigned int constexpr_const = 9600;
int main() {
int x = DEFINE_CONST;
int y = constexpr_const;
std::cout << constexpr_const << std::endl;
std::cout << DEFINE_CONST << std::endl;
}
结果是:
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], 9600 // int x = DEFINE_CONST;
mov DWORD PTR [rbp-8], 9600 // int y = constexpr_const;
// std::cout << constexpr_const << std::endl;
mov esi, 9600
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(unsigned int)
mov esi, OFFSET FLAT:_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
mov rdi, rax
call std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))
// std::cout << DEFINE_CONST << std::endl;
mov esi, 9600
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov esi, OFFSET FLAT:_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
mov rdi, rax
call std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))
mov eax, 0
leave
ret