[英]std::array vs C-Style array for contiguous memory
This is an experimentation for interest only... 这只是出于兴趣的实验...
I'm trying to make a container which holds a fixed number of bytes (eg header) and a dynamic block of data (eg body) all in one contiguous memory block. 我试图使一个容器在一个连续的内存块中容纳固定数量的字节(例如标头)和动态数据块(例如主体)。 In traditional C programming I would have char[0]
as the last instance variable and I would over allocate sizeof(struct) + data_length
. 在传统的C编程中,我将char[0]
作为最后一个实例变量,并且我将过度分配sizeof(struct) + data_length
。
This works in C++ but I want something nicer. 这在C ++中有效,但是我想要更好的东西。 So my question is does a std::array
start with a pointer or can it be used in the same way as a native C-style array? 所以我的问题是std::array
以指针开头,或者可以与本机C样式数组相同的方式使用?
Here's some example code... 这是一些示例代码...
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() );
}
So my question is does a std::array start with a pointer or can it be used in the same way as a native C-style array? 所以我的问题是std :: array是否以指针开头,或者可以与本机C样式数组相同的方式使用?
From the documentation 从文档中
This container is an aggregate type with the same semantics as a struct holding a C-style array T[N] as its only non-static data member. 此容器是一种聚合类型,其语义与将C型数组T [N]作为其唯一的非静态数据成员的结构具有相同的语义。
So there's no other data member in there, just the T[N]
array you wanted. 因此,那里没有其他数据成员,只有您想要的T[N]
数组。
You can trivially confirm this for yourself using sizeof
or looking at the code. 您可以使用sizeof
或查看代码来自己确认一下。
As an aside, names beginning _[AZ]
are reserved for the implementation, so you probably shouldn't be calling your template type parameters _T
and _N
. _N
,以_[AZ]
开头的名称是为实现保留的,因此您可能不应该调用模板类型参数_T
和_N
。
A std::array
doesn't contain any pointer to data somewhere else, a std::array
directly holds the data internally, there's no anything dynamic in there. 一个std::array
在其他地方不包含任何指向数据的指针,一个std::array
直接在内部保存数据,其中没有动态的东西。
It has been designed to provide semantics similar to a standard array but with some characteristics of standard STL containers. 它被设计为提供类似于标准数组的语义,但具有标准STL容器的某些特征。
It's an aggregate class which is mostly implemented as 这是一个聚合类,主要实现为
namespace std
{
template<typename T, size_t S>
class array
{
T __elems_[S];
}
}
You have array.data()
which already returns a C array so I don't get your requirement. 您有array.data()
已经返回一个C数组,所以我没有得到您的要求。
For the reference, the technique you are referring to is called flexible array member
, and unfortunately, it is not supported in C++ as either core feature or standard library function. 作为参考,您所引用的技术称为“ flexible array member
,但是不幸的是,C ++不支持将其用作核心功能或标准库功能。 I find this disappointing. 我觉得这很令人失望。
std::array
is a dressed-up C-style array (with some members which allow it's using as an STL container, like iteration, sizing, type introspection, etc). std::array
是一个经过修饰的C样式数组(某些成员允许将其用作STL容器,例如迭代,调整大小,类型自省等)。
The only way I know to achieve a functionality which would be similar to flexible array member would be to create an std::vector<char>
, with size set to the sizeof(header) + <extra bytes for payload>
, and than placement new
header in the vector.data()
. 我知道实现与灵活数组成员相似的功能的唯一方法是创建一个std::vector<char>
,其大小设置为sizeof(header) + <extra bytes for payload>
,然后placement new
vector.data()
中的placement new
标头。 You can wrap all this in a helper class to save yourself some typing for multiple scenarios. 您可以将所有这些包装在帮助器类中,以节省一些在多种情况下可以输入的内容。
I can suggest type erasure as a general solution to your problem. 我可以建议将类型擦除作为您问题的一般解决方案。 In modern C++ there is a tendency to stay away from direct manipulation of raw pointers, unless inevitable: 在现代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>{}};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.