这只是出于兴趣的实验...
我正在尝试制作一个容器,该容器在一个连续的内存块中都容纳固定数量的字节(例如标头)和动态数据块(例如body)。在传统的C编程中,我将char[0]
作为最后一个实例变量,而我将过度分配sizeof(struct) + data_length
。
这在C ++中有效,但是我想要更好的东西。所以我的问题是std::array
是从指针开始还是可以与本机C样式数组以相同的方式使用?
这是一些示例代码...
struct pkg_base
{
virtual std::size_t get_body_size() = 0;
virtual void *get_body_ptr() = 0;
};
template<typename _T, std::size_t _N>
struct pkg
: public pkg_base
{
std::uint16_t a;
std::uint16_t b;
std::uint16_t c;
std::array<_T, _N> body{};
std::size_t get_body_size() override
{
return ( body.size() );
}
virtual void *get_body_ptr() override
{
return ( body.data() );
}
};
void _test_package()
{
auto vec = std::vector<std::unique_ptr<pkg_base>>{};
vec.push_back(std::make_unique<pkg<char, 1024>>());
vec.push_back(std::make_unique<pkg<float, 1024>>());
vec.push_back( std::make_unique<pkg<std::string, 1024>>() );
auto const size = vec.front()->get_body_size();
auto const *ptr = static_cast<char *>( vec.front()->get_body_ptr() );
}
答案 0 :(得分:3)
所以我的问题是std :: array是从指针开始还是可以以与本机C样式数组相同的方式使用?
此容器是一种聚合类型,其语义与将C型数组T [N]作为其唯一的非静态数据成员的结构相同。
因此,这里没有其他数据成员,只有您想要的T[N]
数组。
您可以使用sizeof
或查看代码来自己确认一下。
顺便说一句,以_[A-Z]
开头的名称是为实现保留的,因此您可能不应该调用模板类型参数_T
和_N
。
答案 1 :(得分:2)
std::array
在其他地方不包含任何指向数据的指针,std::array
直接在内部保存数据,其中没有任何动态信息。
它旨在提供类似于标准数组的语义,但具有标准STL容器的某些特征。
这是一个聚合类,主要实现为
namespace std
{
template<typename T, size_t S>
class array
{
T __elems_[S];
}
}
您有array.data()
已经返回了C数组,所以我不满足您的要求。
答案 2 :(得分:1)
作为参考,您所引用的技术称为flexible array member
,但不幸的是,作为核心功能或标准库功能,C ++不支持该技术。我觉得这很令人失望。
std::array
是一个经过修饰的C样式数组(某些成员可以将其用作STL容器,例如迭代,调整大小,类型自省等)。
我知道要实现与灵活数组成员相似的功能的唯一方法是创建一个std::vector<char>
,其大小设置为sizeof(header) + <extra bytes for payload>
,而不是placement new
标头在vector.data()
中。您可以将所有这些包装在帮助器类中,以节省一些用于多种情况的输入。
答案 3 :(得分:0)
我可以建议将类型擦除作为您问题的一般解决方案。在现代C ++中,除非不可避免,否则有远离原始指针直接操作的趋势:
struct common_part{
//declare common data and ctor
protected:
virtual elem* end(){return begin()+size();};
virtual elem *begin()=0 ;
virtual ~common_part()=default;
virtual std::size_t size()=0;
};
template<std::size_t N>
struct instance_type:
common_part{
protected:
void elem* begin() override{return arr;};
void elem* end() override{return arr+N;};
void std::size_t size() override{return N;};
private:
elem arr[N];
};
std::unique_ptr<common_part> ptr {new instance_type<N>{}};