在不增加内存的情况下将预处理器配置定义迁移到constexpr。

问题描述 投票:0回答:1

迟来总比不来好:我正试图更新我的代码库以适应最新的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值的概念,有谁能给我指出正确的方向?谢谢

c++ c++14 constexpr
1个回答
2
投票

你总是可以使用像 godbolt 这样的工具来查看编译器创建的内容。如果你检查结果为 这套 你会发现,编译器将为你的 #definecostexpr如果你只将它们作为常量使用,即使没有开启优化功能。

#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
© www.soinside.com 2019 - 2024. All rights reserved.