创建在c ++中的结构内声明的数组a [1]的多个实例

时间:2018-05-09 09:39:12

标签: c++ data-structures

假设我有两个结构如下:

struct address{
  int x;
  int y;
} addr;

struct details{
  int count;
  int size;
  addr addre[1];// Instances of count number of addresses
} detail;                 

如何创建一个变量,比如det,它有多个addre个实例,由计数编号定义?

3 个答案:

答案 0 :(得分:2)

这是减少内存分配数量和改进引用位置的常用技巧,方法是在对象末尾分配动态大小的容器(具有固定大小)。

在C ++中,使用额外的member[1]会导致一些麻烦 - 该成员会自动初始化,而其余元素则不会。最好避免声明该成员,而是为元素提供访问器/迭代器。然后手动初始化并销毁所有成员。 E.g:

struct address {
    int x;
    int y;
};

struct details {
    int count;
    int size;

    address* addr_begin() { return reinterpret_cast<address*>(this + 1); }
    address* addr_end() { return addr_begin() + count; }

    static void* operator new(size_t sizeof_details, int count) {
        return ::operator new(sizeof_details + count * sizeof(address));
    }

    static void operator delete(void* p) {
        ::operator delete(p);
    }

    static std::unique_ptr<details> create(int count, int size) {
        return std::unique_ptr<details>(new(count) details(count, size));
    }

    ~details() {
        std::for_each(addr_begin(), addr_end(), [](address& a) { a.~address(); });
    }

private:
    details(int count, int size)
        : count(count)
        , size(size)
    {
        std::uninitialized_fill(addr_begin(), addr_end(), address{});
    }
};

int main() {
    auto det = details::create(10, 10);
}

如果你不能改变结构,那么:

#include <new>
#include <algorithm>

struct address {
    int x;
    int y;
};

struct details {
    int count;
    int size;
    address addre[1];
};

details* create_details(int count, int size) {
    void* mem = ::operator new(sizeof(details) + (count - 1) * sizeof(address));
    auto* p = new (mem) details{count, size};
    std::uninitialized_fill(p->addre + 1, p->addre + count, address{});
    return p;
}

void destroy_details(details* p) {
    std::for_each(p->addre + 1, p->addre + p->count, [](address& a) { a.~address(); });
    p->~details();
    ::operator delete(p);
}

int main() {
    auto* p = create_details(10, 10);
    destroy_details(p);
}

答案 1 :(得分:0)

如果我的问题正确(我不确定,因为它不太清楚),你有一个结构

struct address {
  int x;
  int y;
};

并且您想要定义另一个details,其中包含details.count address个实例的集合。你基本上有两个选择。

details.count在编译时已知

在这种情况下,您最好的选择是将count定义为非类型模板参数并使用std::array

template <std::size_t COUNT>
struct details {
    static constexpr std::size_t count = COUNT;
    std::array<address, COUNT> addresses;
};

// ...

details<42> det;
// det.addresses[0] to det.addresses[41] are valid (but uninitialized) addresses

details.count在编译时未知

在这种情况下,您最好的选择是使用std::vector并在构造中提供count,甚至在构建后将address添加到details.addresses

struct details {
    std::vector<address> addresses;
};

// ...

details det;
det.addresses.emplace_back(address{0, 0}); // adds and initializesdet.addresses[0]

答案 2 :(得分:0)

YSC殴打几秒钟,只留下一些补充:

如果你需要额外的尺寸和容量,你甚至可以直接使用矢量:

using Details = std::vector<address>;

由于您显然需要大小和容量,因此使用std :: array执行相同操作可能无法满足您的需求,因此您可能会继续使用聚合...