c++ - 将预处理器配置定义迁移到没有内存膨胀的 constexpr
问题描述
迟到总比没有好:我正在尝试将我的代码库更新为最新的 C++ 标准,现在正试图真正理解 constexpr 语法功能的意图。
但是,我正在为此苦苦挣扎:在我的一个微控制器项目中(没有一些高级 std 功能的纯 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
and生成相同的输出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
推荐阅读
- r - 在闪亮的应用程序中加载 rhandsontable 时,如何通过 updateSliderInput 更新滑块?
- angular - 使用 Angular-Cli 加载外部框架
- model-view-controller - Umbraco 问题得到寒冷的属性
- java - java.lang.IllegalArgumentException 如果尝试读取 Excel 表,则会出现异常
- eclipselink - Eclipselink 共享缓存 - 延迟关联
- python - xgboost 错误:不是有效的 Win32 应用程序
- javascript - 移动设备上的 Google 地图缩放级别
- jquery - 如何在剃刀页面中为模型提供 ID 以在 jquery 脚本中使用
- sql - msg 8152 级别 16 状态 2 字符串或二进制数据将被截断
- c++ - 如何在 C++ 中的 .so 文件中包含库