【问题标题】:Initializing statically sized arrays for types without a default constructor为没有默认构造函数的类型初始化静态大小的数组
【发布时间】:2019-04-21 10:03:34
【问题描述】:

我正在编写一个简单的模板循环缓冲区:

template <typename T, size_t N>
class CircularBuffer {

    T      _buf[N];
    T     *_data;
    size_t _head;
    size_t _count;
    size_t _capacity;

    CircularBuffer():
            _data(nullptr),
            _head(0),
            _count(0),
            _capacity(N) {}

protected:

    T* buffer() {
        if (_count <= N) return &_buf;
        else return _data;
    }

public:

    T& operator[](size_t i) {
        size_t j = i % _count;
        j = (_head + j) % _capacity;
        return buffer()[j];
    }

    T& push_back(const T& o) {
        if (_count == _capacity) {
            dynamically_allocate_data();
        }
        size_t j = (_head + _count++) % _capcity;
        buffer()[j] = o;
    }

    T pop_front() {
        size_t old_head = _head;
        _head = (_head + 1) % _capacity;
        return buffer()[old_head];
    }

};

这是从真实的东西中剥离出来的,但它并不遥远,你明白了。这样可以避免为小于 N 个项目的缓冲区分配内存。

问题是这不适用于没有默认构造函数的T。我可以为CircularBuffer 提供一个构造函数——也就是std::vector's——它接受一个T 来填充空缓冲区,但我不确定如何在不隐式调用T 的情况下实际实现它的(可能不存在的)默认构造函数。

对类似问题的回复建议使用 std::vector 或将 new 放置在 void* 数组上,但在这种情况下不适用,因为重点是避免在内部循环中动态分配内存。

如何在没有默认构造函数的情况下为T 构造此类? (或者,是否有另一种方案可以避免在缓冲区中构造空白T?)

【问题讨论】:

  • placement new分配内存。
  • 你可以在这个角色中使用placement new
  • @appleapple 如何声明void* 的静态数组?
  • 你可以使用(unsigned) char[]
  • 您想要std::aligned_storage 和新的展示位置。

标签: c++ arrays templates constructor default-constructor


【解决方案1】:

使用std::optional(或boost::optional,如果你的编译器是pre-17)怎么样?您可以将静态数组定义为std::optional&lt;T&gt; _buf[N];

std::optional 类型支持放置构造(因此T 不需要默认构造函数)并静态分配,这样就可以满足您的要求,不是吗?

【讨论】:

    猜你喜欢
    • 2011-06-12
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多