让我们以自定义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
。请给我一些提示。
答案 0 :(得分:3)
就这么简单
for (int i = 0; i < _size; i++)
_buff[i] = Object{};
或者,您可以摆脱循环并在此处添加一对{}
(或()
):
_buff = new Object[_capasity]{};
// ^^
但是此选项将对所有_capasity
个对象进行值初始化,而不是@bipll所指出的第一个_size
个对象。
此外,请注意,如果您想模仿std::vector
的行为,则需要分配原始存储空间(可能是std::aligned_storage
)并手动调用构造函数(通过placement-new)和析构函数。
如果Object
是类类型,则_buff = new Object[_capasity];
会为所有_capasity
对象调用默认构造函数,而不是像_size
那样为第一个std::vector
对象调用默认构造函数。
答案 1 :(得分:1)
请注意,致电时
_buff = new Object[_capasity];
(顺便说一句,为什么要将此初始化从init-list中移到构造函数主体中?)您已经具有默认初始化的_capasity
对象。默认初始化在这里具有以下效果:虽然标量类型的元素将保持未初始化(并从UB读取),但对于类类型,您已经调用了_capasity
构造函数。
为避免不必要的构造,您可以选择以下选项:
使用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
}
请记住,向量增长时buff_
应该再次aligned_alloc
(对于琐碎的类型可以std::realloc()
ed),在析构函数中应该std::free()
d —和在此之前,应销毁其中的size_
对象(显式调用~Object()
)。
将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。