简体   繁体   English

std :: array与C-Style数组的连续内存

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM