使用しないでくださいstd::memcpy
std::memcpy
単純にコピー可能なオブジェクトでのみ使用できます。それ以外の場合は、未定義の動作です。
ただし、すべての要素を手動でコピーすることはできます。std::copy
自明な型に特化している可能性があるため、適切です。
実際には、 の実装では複数の代入を避け、値の型が TriviallyCopyable の場合std::copy
などに一括コピー関数を使用しますstd::memcpy
template <typename T>
void Vector<T>::push_back(const T& item) {
if (_size == _capacity) {
size_t new_cap = _capacity > 0 ? 2 * _capacity : 2;
T * newVec = new T[new_cap];
std::copy(_ptr, _ptr + _size, newVec);
std::swap(_capacity, new_cap);
std::swap(_ptr, newVec);
delete[] newVec;
}
_ptr[_size++] = item;
}
ベクトルが小さすぎる場合、元の実装では容量が分割されることに注意してください。
その他の改善
(または互換性のあるクラス)を使用するstd::allocator
と、少し簡単になります。を使用.allocate
して、メモリを取得.construct(pointer, value)
し、実際にオブジェクトを構築.destroy
し、それらのデストラクタを呼び出し、.deallocate
以前に で作成されたメモリを削除し.allocate
ます。したがって、単に使用したい場合は、デフォルトの構築可能なオブジェクトは必要ありません.push_back()
。
次のコードは、簡単な最小限のスケッチです。reserve()
コンストラクターがスローした場合、割り当てられたメモリをtmp
クリーンアップする必要があるため、例外セーフではないなど、いくつかの問題があることに注意してください。
template <typename T, class Allocator = std::allocator<T> >
class Vector{
public:
typedef typename Allocator::pointer pointer;
typedef typename Allocator::size_type size_type;
Vector() : _ptr(0), _capacity(0), _size(0){}
~Vector() {
if(_capacity == 0)
return;
while(_size > 0)
pop_back();
_alloc.deallocate(_ptr, _capacity);
}
void reserve(size_type new_cap){
if(new_cap <= _capacity)
return;
// allocate memory
T * tmp = _alloc.allocate(new_cap);
// construct objects
for(unsigned int i = 0; i < _size; ++i){
_alloc.construct(tmp + i, _ptr[i]); // or std::move(_ptr[i])
}
// finished construction, save to delete old values
for(unsigned int i = 0; i < _size; ++i){
_alloc.destroy(_ptr + i);
}
// deallocate old memory
_alloc.deallocate(_ptr, _capacity);
_ptr = tmp;
_capacity = new_cap;
}
void push_back(const T& val){
if(_size == _capacity)
reserve(_capacity > 0 ? 2 * _capacity : 1);
_alloc.construct(_ptr + _size, val);
_size++; // since T::T(..) might throw
}
void pop_back(){
_alloc.destroy(_ptr + _size - 1);
_size--;
}
T& operator[](size_type index){
return _ptr[index];
}
private:
pointer _ptr;
size_type _capacity;
size_type _size;
Allocator _alloc;
};