簡體   English   中英

std :: array與C-Style數組的連續內存

[英]std::array vs C-Style array for contiguous memory

這只是出於興趣的實驗...

我試圖使一個容器在一個連續的內存塊中容納固定數量的字節(例如標頭)和動態數據塊(例如主體)。 在傳統的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() );
}

所以我的問題是std :: array是否以指針開頭,或者可以與本機C樣式數組相同的方式使用?

文檔中

此容器是一種聚合類型,其語義與將C型數組T [N]作為其唯一的非靜態數據成員的結構具有相同的語義。

因此,那里沒有其他數據成員,只有您想要的T[N]數組。

您可以使用sizeof或查看代碼來自己確認一下。

_N ,以_[AZ]開頭的名稱是為實現保留的,因此您可能不應該調用模板類型參數_T_N

一個std::array在其他地方不包含任何指向數據的指針,一個std::array直接在內部保存數據,其中沒有動態的東西。

它被設計為提供類似於標准數組的語義,但具有標准STL容器的某些特征。

這是一個聚合類,主要實現為

namespace std
{
  template<typename T, size_t S>
  class array
  {
    T __elems_[S];
  }
}

您有array.data()已經返回一個C數組,所以我沒有得到您的要求。

作為參考,您所引用的技術稱為“ flexible array member ,但是不幸的是,C ++不支持將其用作核心功能或標准庫功能。 我覺得這很令人失望。

std::array是一個經過修飾的C樣式數組(某些成員允許將其用作STL容器,例如迭代,調整大小,類型自省等)。

我知道實現與靈活數組成員相似的功能的唯一方法是創建一個std::vector<char> ,其大小設置為sizeof(header) + <extra bytes for payload> ,然后placement new vector.data()中的placement new標頭。 您可以將所有這些包裝在幫助器類中,以節省一些在多種情況下可以輸入的內容。

我可以建議將類型擦除作為您問題的一般解決方案。 在現代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