带constexpr构造函数的类实例成员能否确保存入ROM?
关于constexpr引用成员存储位置的问题
问题背景
给出如下结构体定义:
struct Configuration { public: constexpr Configuration(Interface& iface, Interface& iface2, Interface& iface3):iface_(iface),iface2_(iface2),iface3_(iface3) {} Interface& iface_; Interface& iface2_; Interface& iface3_; };
并通过以下代码实例化:
constexpr Configuration conf{cl, cl, cl};
针对无操作系统的ARM控制器平台,使用GCC/IAR编译器时,存在以下疑问:能否确保该实例的三个引用成员被存入ROM?还是仅构造函数在编译期调用,但数据仍存入RAM?或是该行为完全取决于编译器?
解答
首先要明确:C++中的引用在底层是通过指针实现的,所以Configuration的三个成员本质上对应三个指针值。
- 若
cl是具有静态存储周期且地址固定的对象(比如全局/静态作用域的Interface实例),那么conf的三个引用成员对应的指针值是编译期可确定的常量。对于ARM裸机平台的GCC和IAR编译器来说,都会将constexpr修饰的conf放入只读存储区(ROM),这是嵌入式编译器的常规优化行为,也是符合开发者预期的结果。 - 若
cl是局部自动变量,其地址在编译期无法确定,此时constexpr实例化会直接编译失败——因为constexpr要求引用绑定的对象必须是编译期可寻址的常量表达式。 - 仅构造函数编译期调用但数据存入RAM的情况几乎不会出现:
constexpr变量的核心要求是其值在编译期确定,在资源紧张的嵌入式平台上,编译器没有理由将编译期常量放到RAM中占用宝贵的随机存取内存资源。
总结:只要cl符合常量表达式要求的静态存储期对象,GCC/IAR会把conf的三个引用成员(即指针值)存入ROM;若cl不符合要求,代码无法通过编译。严格来说C++标准并未强制要求常量必须放入ROM,但目标平台的主流嵌入式编译器都会执行该优化,行为是可预期的。
内容的提问来源于stack exchange,提问作者Oliver S.
相关产品推荐
相关产品推荐

