StrVec可以看我之前写个。
因为写完本篇程序发现个奇怪的问题,程序用vec就没事,用vec就炸,排查了一下又是越界问题。这里吹一下vs,debug功能好强啊,因为string释放时会调用析构,导致free函数释放时多释放了一个空的指针。但基础类型销毁的时候没有析构函数所以没事。
完整代码
#include <iostream>
#include<string>
#include<vector>
#include<list>
#include<memory>
template <typename elemType> class vec {
public:
vec() :elements(nullptr), first_free(nullptr), cap(nullptr) {}
vec(std::initializer_list<elemType>);
vec(const vec&);
vec& operator=(const vec<elemType>&);
~vec();
void push_back(const elemType&);
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
size_t reserve(size_t);
//size_t resize(size_t);
elemType* begin() const { return elements; }
elemType* end() const { return first_free; }
void print_message(); //bebug
private:
std::allocator<elemType> alloc ;
void chk_n_alloc();
std::pair<elemType*, elemType*> alloc_n_copy(const elemType*, const elemType*);
void free();
void reallocate();
elemType* elements; //第一个元素
elemType* first_free; //最后一个元素的后一个
elemType* cap; //最后一个空间
};
template <typename elemType>
void vec<elemType>::chk_n_alloc() {
if (size() == capacity())
reallocate();
}
template <typename elemType>
void vec<elemType>::free(){
if (elements) {
for (auto p = first_free; p != elements; p--)
alloc.destroy(--p);
alloc.deallocate(elements, cap - elements);
}
}
template <typename elemType>
void vec<elemType>::reallocate() {
auto newcapacity = size() ? 2 * size() : 1;
auto newdata = alloc.allocate(newcapacity);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elem));
free();
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
}
template <typename elemType>
vec<elemType>::vec(std::initializer_list<elemType> s) {
reserve(2 * s.size());
auto dest = elements;
for (auto i : s)
alloc.construct(dest++, i);
first_free = dest;
}
template <typename elemType>
std::pair<elemType*, elemType*> vec<elemType>::alloc_n_copy(const elemType* b, const elemType* e) {
auto data = alloc.allocate(e - b);
return { data,std::uninitialized_copy(b,e,data) };
}
template <typename elemType>
vec<elemType>::vec(const vec& s) {
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = newdata.second;
}
template <typename elemType>
vec<elemType>::~vec() {
free();
}
template <typename elemType>
vec<elemType>& vec<elemType>::operator=(const vec<elemType> &s) {
auto data = alloc_n_copy(s.begin(), s.end());
free();
elements = data.first;
first_free = cap = data.second;
return *this;
}
template <typename elemType>
void vec<elemType>::push_back(const elemType& n) {
chk_n_alloc();
alloc.construct(first_free++, n);
}
template <typename elemType>
void vec<elemType>::print_message() {
for (auto i = begin(); i != end(); ++i)
std::cout << *i << " ";
}
template <typename elemType>
size_t vec<elemType>::reserve(size_t n) {
auto newcapacity = n;
auto old_size = size();
if (newcapacity < old_size)
old_size = n;
auto newdata = alloc.allocate(newcapacity);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != old_size; ++i)
alloc.construct(dest++, std::move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
return cap - elements;
}
int main() {
vec<std::string> s = { "a","v","c" };
s.push_back("f");
vec<int> t = { 1,2,3,4 };
t.push_back(5);
s.print_message();
t.print_message();
}