0

让我们以自定义vector实现为例:

template<typename Object>
class myVector {
public:
    explicit myVector(int size = 0) :
        _size{ size },
        _capasity{ size + SPARE_CAPACITY }
    {
        _buff = new Object[_capasity];
        if (_size > 0) {
            for (int i = 0; i < _size; i++) {
                //_buff[i] = 0;
            }
        }
    }

// more code

private:
    Object * _buff = nullptr;
    int _size;
    int _capasity;
};

所以我的问题是,如何进行myVector值初始化,以防我将其初始化为:

int main() {
    myVector<int> v02(5);                   
}

在这里,它包含 5 个int值,所以我需要它全为零;与其他类型相同。我注释掉了,_buff[i] = 0;因为它是特定于int. 请给我一些提示。

4

2 回答 2

3

It's as simple as

for (int i = 0; i < _size; i++)
    _buff[i] = Object{};

Alternatively, you could get rid of the loop and add a pair of {} (or ()) here:

_buff = new Object[_capasity]{};
//                           ^^

But this option would value-initialize all _capasity objects, rather than the first _size ones, as noted by @bipll.


Also, note that if you want to mimic the behavior of std::vector, you need to allocate raw storate (probably std::aligned_storage) and call constructors (via placement-new) and destructors manually.

If Object is a class type, _buff = new Object[_capasity]; calls default constructors for all _capasity objects, rather than for the first _size objects as std::vector does.

于 2018-12-29T08:24:56.213 回答
1

请注意,调用时

        _buff = new Object[_capasity];

(顺便说一句,你为什么把这个初始化从初始化列表中移到构造函数体中?)你已经有了默认初始化的_capasity对象。默认初始化在这里具有以下效果:虽然标量类型的元素将保持未初始化(并从它们读取 UB),但对于您已经调用_capasity构造函数的类类型。

为避免不必要的构造,您有以下可能的选择,其中包括:

  1. 使用std::aligned_alloc分配未初始化的内存:

    explicit myVector(std::size_t size = 0) :
        size_{ size }
        , capacity_{ size + SPARE_CAPACITY }
        , buff_{std::aligned_alloc(alignof(Object), _capacity)}
    {
        if(!buff_) throw std::bad_alloc();
        if(size) new (buff_) Object[size]{}; // empty braces answer your original query
    }
    

    请记住,当 vector 增长时,buff_应该再次aligned_alloced (对于普通类型可以std::realloc()ed ),在析构函数中它应该是std::free()d - 并且在size_它内部的对象之前应该被破坏(通过显式调用~Object())。

  2. 将 的类型更改buff_为更简单但正确对齐的类型:

        using Storage = std::aligned_storage_t<sizeof(Object), alignof(Object)>;
        Storage *buff_;
        Object *data_ = nullptr;
    public:
        explicit myVector(std::size_t size = 0) :
            size_{ size }
            , capacity_{ size + SPARE_CAPACITY }
            , buff_{new Storage(_capacity)}
        {
            if(size) data_ = new (buff_) Object[size]{};
        }
    

    同样,在析构函数中,对象应该被手动销毁,但这一次buff_可以简单地delete[]d 之后。

于 2018-12-29T09:08:12.347 回答