我正在使用C++14开发一个带有MPU的ARM处理器的嵌入式系统,我想在初始化期间减少动态分配的数量,因为我更想知道链接时使用的确切内存量。
在C99中,您可以使用复合文字在堆栈或全局范围上分配内存,请参阅以下无意义代码,它在编译时在结构中分配结构:
struct Foo {
struct Foo* next;
};
struct Foo *bar = {
&(struct Foo){
&(struct Foo){ NULL }
}
};
不可能使用任何GCC或Clang扩展来解决这个问题,只能使用纯C++14代码。
我发现,模仿这种行为的唯一简单方法是使用lambda函数。然而,这个解决方案是不可重入的。
struct Foo* bar = [](){
static struct Foo bar = {
static struct Foo bar = { nullptr };
return &bar;
}();
return &bar;
}();
lambda解决方案适用于我的情况,我可以使用宏使其使用起来更舒适,但如果我想将数据结构放在堆栈上,它就不是一个解决方案。
解决这个问题的最佳C++方法是什么(不使用动态分配(?
我目前试图解决的问题是派生类的树,我想在编译时分配它。
我试图在想象中的C++代码中实现的目标:
RootClass* b = &(DerivedClass1){ &(DerivedClass2){10},
&(DerivedClass2){20},
&(DerivedClass1){ &(DerivedClass0){} }
};
我试图在想象中的C++代码中实现的目标:
好吧,永远不会工作。没有要求这些派生类中的任何一个与基类大小相同,因此不可能在基类上进行指针运算(即使C++允许在基类上对指向元素类型为派生类的数组的指针进行指针运算。而不允许(。
如果你处理的是单一类型的T
,那么你可以这样做:
T ts[] = {<initializers>};
您可以根据需要使用ts
。但这只适用于适当的数组。
现在,如果你想做派生类的事情,你可以总是使用tuple
作为派生类元素的容器,然后构建一个指向基类元素的指针数组,这样你就可以从一个元素迭代到另一个元素。C++14让这有点麻烦,因为它需要在tuple
类型本身中列出类型,但C++17的类模板参数推导使它更容易理解:
auto tpl = tuple(DerivedClass2{10}, DerivedClass2{20}, DerivedClass1{DerivedClass0{}});
C++14版本只是重复这些类型。
构建数组需要一些模板元编程技术:
template<typename BC, typename Tpl, std::size_t ...ixs>
auto GetBaseClassArrayHelper(Tpl &tpl, std::index_sequence<ixs...>)
{
return std::array<BC*, std::tuple_size<Tpl>::value>{static_cast<BC*>(std::get<ixs>(tpl))...};
}
template<typename BC, typename Tpl>
std::array<BC*, std::tuple_size<Tpl>::value> GetBaseClassArray(Tpl &tpl)
{
return GetBaseClassArrayHelper<BC>(tpl, std::make_index_sequence<std::tuple_size<Tpl>::value>{});
}
现在,这不允许您将BaseClass*
和++
转换为不同的BaseClass*
。为了做到这一点,您需要在指针数组中有一个指针,一个BaseClass**
。