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

时间:2018-07-13 12:37:55

标签: c++ c++11 stl

这只是出于兴趣的实验...

我正在尝试制作一个容器,该容器在一个连续的内存块中都容纳固定数量的字节(例如标头)和动态数据块(例如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() );
}

4 个答案:

答案 0 :(得分:3)

  

所以我的问题是std :: array是从指针开始还是可以以与本机C样式数组相同的方式使用?

来自the documentation

  

此容器是一种聚合类型,其语义与将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>{}};