我有大量使用constexpr构造函数构造的静态常量对象,因此它们无需任何构造函数调用即可立即存储在最终二进制文件中。
由于我正在使用内存较低的系统(STM32 MCU),因此我想减少这些对象的内存占用,并且由于它们是恒定的,因此请将其存储在该.rodata部分中。编译器对此进行了顺利处理。
但是,既然我已在基类中添加了虚拟析构函数以删除编译器警告,则对象将存储在该.data部分中。
当然,我可以使用某些方法#pragma专门删除基类的编译器警告,并删除虚拟析构函数,但是我想知道是否有更干净的解决方案。
极简主义代码展示了这个问题:
class Object {
int value;
public:
constexpr Object(int param)
: value(param) {}
virtual int getValue() const = 0;
virtual ~Object() = default; // This line causes problems
};
class Derived : public Object {
volatile int otherValue;
public:
constexpr Derived(int param1, int param2)
: Object(param1), otherValue(param2) {}
int getValue() const override { return otherValue; }
};
const Derived instance(1,2);
int main() {
return instance.getValue();
}
Run Code Online (Sandbox Code Playgroud)
另外,这是一个CompilerExplorer,可以在有和没有虚拟析构函数的情况下进行比较:https : //godbolt.org/z/M5G7LO
声明虚拟方法后,便向该类添加了一个非恒定指针,该指针指向该类的虚拟表。该指针将首先被初始化为Object的虚拟表,然后在整个构造函数链中继续更改为派生类的虚拟指针。然后,它将在析构函数链中再次更改并回滚,直到指向对象的虚拟表为止。这意味着您的对象不再可以是纯只读对象,而必须移出.rodata。
较干净的解决方案是忽略类中的任何虚函数,或者完全避免继承,并使用模板将所需的虚函数调用替换为编译时调用。
| 归档时间: |
|
| 查看次数: |
301 次 |
| 最近记录: |