赞
踩
目前学到第十四章,对继承不熟,因此没有用到14.5.6中的vector_base类,因而没有实现vector类的RAII。
//Vector_template.h #include<iostream> #include"14_8-Allocator.h" //使用模板需要注意,目前VS2019都要求在使用模板的地方必须能得到模板的完整定义 //因此,我们将模板的定义都放在了头文件中 template<typename T, typename A = allocator<T>> class vector { static const int first_expand_space{ 8 }; A alloc; //用 alloc 管理元素内存 int sz; //元素数目 int space; //总空间 = 元素数目 + 给新元素的空闲空间(槽位);总空间是指当前分配的空间 T* elem; public: class Invalid {}; struct out_of_range { /*...*/ }; //用来报告越界错误 vector(); //默认构造函数 explicit vector(int x, T def = T{}); //构造函数,x为元素数量,def为初始化值,在定义中有默认值 vector(std::initializer_list<T>lst); //初始化器列表构造函数 vector(const vector&); //拷贝构造函数 vector& operator=(const vector&); //拷贝赋值函数 vector(vector&&); //移动构造函数 vector& operator=(vector&&); //移动赋值函数 int size() const; void reserve(int newalloc); //改变 space 的大小 int capacity()const; //返回 space 的大小 void resize(int newalloc, T def = T{}); //该表元素数量 void push_back(const T& val); T& operator[](int n); const T& operator[](int n) const; T& at(int n); const T& at(int n) const; ~vector(); }; //下面是定义 template<typename T, typename A> vector<T, A>::vector() :sz{ 0 }, space{ 0 }, elem{ nullptr } { } template<typename T, typename A> vector<T, A>::vector(int x, T def) //构造函数,x为元素数量 : sz{ x }, space{ x } { if (x < 0) throw Invalid{}; elem = alloc.allocate(x); for (int i = 0; i < sz; i++) alloc.construct(elem + i, def); //初始化 } template<typename T, typename A> vector<T, A>::vector(std::initializer_list<T> lst) //初始化器列表构造函数 :sz{ int(lst.size()) }, space{ int(lst.size()) }, elem{ alloc.allocate(lst.size()) } { //std::cout << "初始化列表构造函数\n"; const T* ti = lst.begin(); for (int i = 0; i < sz; ++i) alloc.construct(elem + i, *ti++); //初始化 } template<typename T, typename A> vector<T, A>::vector(const vector& arg) //拷贝构造函数 : sz{ arg.sz }, space{ arg.space }, elem{ alloc.allocate(arg.space) } { //std::cout << "拷贝构造函数\n"; for (int i = 0; i < sz; ++i) alloc.construct(elem + i, arg.elem[i]); } template<typename T, typename A> vector<T, A>& vector<T, A>::operator=(const vector& arg) //拷贝赋值函数 { //std::cout << "拷贝赋值函数\n"; if (this == &arg) //自赋值,什么也不用做 ; else if (arg.sz <= space) //空间足够,无需分配空间 { for (int i = 0; i < sz; ++i) alloc.destroy(elem + i); //先销毁原来的元素 for (int i = 0; i < arg.sz; ++i) alloc.construct(&elem[i], arg.elem[i]); //拷贝元素 sz = arg.sz; } else { T* p = alloc.allocate(arg.sz); for (int i = 0; i < arg.sz; ++i) alloc.construct(p + i, arg.elem[i]); //拷贝元素 alloc.deallocate(elem, space); sz = space = arg.sz; //设置新大小 elem = p; //指向新元素的指针 } return *this; //按照惯例,赋值运算符将返回被赋值对象的引用 } template<typename T, typename A> vector<T, A>::vector(vector&& arg) //移动构造函数 :sz{ arg.sz }, space{ arg.space }, elem{ arg.elem } { //std::cout << "移动构造函数\n"; arg.sz = arg.space = 0; //令 arg 变为空 arg.elem = nullptr; } template<typename T, typename A> vector<T, A>& vector<T, A>::operator=(vector&& arg) //移动赋值函数,将 arg 移动到本vector { //std::cout << "移动赋值函数\n"; alloc.deallocate(elem, space); sz = arg.sz; space = arg.space; elem = arg.elem; arg.sz = arg.space = 0; arg.elem = nullptr; return *this; } template<typename T, typename A> int vector<T, A>::size() const { return sz; } template<typename T, typename A> void vector<T, A>::reserve(int newalloc) { if (newalloc <= space) //永远不会减少分配的空间 return; T* p = alloc.allocate(newalloc); //分配新空间 for (int i = 0; i < sz; ++i) alloc.construct(&p[i], elem[i]); //拷贝现有元素 for (int i = 0; i < sz; ++i) alloc.destroy(&elem[i]); //销毁现有元素 alloc.deallocate(elem, space); //释放旧空间 elem = p; space = newalloc; } template<typename T, typename A> int vector<T, A>::capacity() const { return space; } template<typename T, typename A> void vector<T, A>::resize(int newsize, T def) //令 vector 有 newsize 个元素 //newsize 必须 >= 0 //用默认值 def 初始化每个新元素 { if (newsize < 0) throw Invalid{}; reserve(newsize); for (int i = newsize; i < sz; ++i) alloc.destroy(elem + i); //销毁从newsize开始的元素 for (int i = sz; i < newsize; ++i) alloc.construct(&elem[i], def); //用默认值初始化 sz = newsize; } template<typename T, typename A> void vector<T, A>::push_back(const T& val) //将 vector 的大小增加1:用 val 初始化新元素 { if (space == 0) reserve(first_expand_space); else if (sz >= space) reserve(space * 2); alloc.construct(&elem[sz], val); ++sz; } template<typename T, typename A> T& vector<T, A>::operator[](int n) { return elem[n]; } template<typename T, typename A> const T& vector<T, A>::operator[](int n) const { return elem[n]; } template<typename T, typename A> T& vector<T, A>::at(int n) { if (n < 0 || sz <= n) throw out_of_range(); return elem[n]; } template<typename T, typename A> const T& vector<T, A>::at(int n) const { if (n < 0 || sz <= n) throw out_of_range(); return elem[n]; } template<typename T, typename A> vector<T, A>::~vector() { for (int i = 0; i < sz; ++i) alloc.destroy(elem + i); //释放之前要销毁对象元素 alloc.deallocate(elem, space); }
#include"../../std_lib_facilities.h"
template<typename T> void f(vector<T>& v1, const vector<T>& v2)
{
if (v1.size() != v2.size())
{
cerr << "two vectors have different size\n";
return;
}
for (int i = 0; i < v1.size; ++i)
v1[i] += v2[i];
}
#include"../../std_lib_facilities.h"
template<typename T, typename U> //T和U的限制为可以做乘法和加法的类型
T in_product(const vector<T>& vt, const vector<U>& vu)
{
T res{ 0 };
if (vt.size() != vu.size())
{
cerr << "two vectors have different size\n";
return res;
}
for (int i = 0; i < vt.size(); ++i)
res += vt[i] * vu[i];
return res;
}
#include"../../std_lib_facilities.h" template<typename T> class Pair { string var_name; T val; public: Pair(string n, T v) :var_name{ n }, val{ v }{ } string get_name() { return var_name; } string get_name()const { return var_name; } T get_val() { return val; } const T& get_val()const { return val; } void change_val(T v) { val = v; } }; vector<Pair<double>> var_tbl; bool is_declared(string var) { for (const Pair<double>& v : var_tbl) if (v.get_name() == var) return true; return false; } double define_name(string var, double val) { if (is_declared(var)) error(var, " declared twice"); var_tbl.push_back(Pair<double>{var, val}); return val; }
#include"../../std_lib_facilities.h" struct God { string name; string mythology; string mount; string weapon; }; template<typename T> class Link { public: T god; Link(const God& g, Link* p = nullptr, Link* s = nullptr) :god{ g }, pred{ p }, succ{ s } { } Link* insert(Link* n); //在此对象之前插入n Link* add(Link* n); //在此对象之后插入n Link* add_order(Link* n); //按字典序将n放置在正确位置中 Link* erase(); //将此对象从链表中删除 Link* find(const string& s); //在链表中查找s const Link* find(const string& s) const; //在const链表中查找s Link* advance(int n); //在链表中移动n个位置 Link* next() const { return succ; } Link* prev() const { return pred; } private: Link* pred; Link* succ; }; template<typename T> void print_all(Link<T>* p); int main() try { Link<God>* norse_gods = new Link<God>{ God{"Thor", "Norse","",""} }; norse_gods = norse_gods->add_order(new Link<God>{ God{"Odin", "Norse","Eight-legged flying horse called Sleipner",""} }); norse_gods = norse_gods->add_order(new Link<God>{ God{"Freia", "Norse", "",""} }); print_all(norse_gods); cout << '\n'; Link<God>* greek_gods = new Link<God>{ God{"Hera","Greek","",""} }; greek_gods = greek_gods->insert(new Link<God>{ God{"Athena","Greek","",""} }); greek_gods = greek_gods->add_order(new Link<God>{ God{"Ares" ,"Greek", "", ""} }); greek_gods->add_order(new Link<God>{ God{"Zeus","Greek","",""} }); greek_gods->add_order(new Link<God>{ God{"Poseidon","Greek","","Trident"} }); print_all(greek_gods); cout << '\n'; print_all(greek_gods->advance(2)); cout << '\n'; return 0; } catch (runtime_error& e) { cerr << "Runtime error: " << e.what() << endl; return 1; } catch (...) { cerr << "Exception occured!\n"; return 2; } template<typename T> Link<T>* Link<T>::insert(Link<T>* n) //在此对象之前插入n { if (n == nullptr) return this; if (this == nullptr) return n; n->succ = this; n->pred = pred; if (pred) pred->succ = n; pred = n; return n; } template<typename T> Link<T>* Link<T>::add(Link<T>* n) //在此对象之后插入n { if (n == nullptr) return this; if (this == nullptr) return n; n->pred = this; n->succ = succ; if (succ) succ->pred = n; succ = n; return this; } template<typename T> Link<T>* Link<T>::add_order(Link<T>* n) //按字典序将n放置在正确位置中;返回在前的元素 { if (n == nullptr) return this; if (this == nullptr) return n; Link<T>* header = this; if (n->god.name < header->god.name) { n->pred = pred; n->succ = this; pred = n; header = n; } else if (n->god.name > header->god.name) { Link<T>* p; for (p = this; p->succ && n->god.name > p->succ->god.name; p = p->next()) continue; n->succ = p->succ; n->pred = p; if (p->succ) p->succ->pred = n; p->succ = n; } return header; } template<typename T> Link<T>* Link<T>::erase() //将此对象从链表中删除;返回该对象的后继 { if (this == nullptr) return nullptr; if (pred) pred->succ = succ; if (succ) succ->pred = pred; return succ; } template<typename T> Link<T>* Link<T>::find(const string& name) //在链表中查找s { Link<T>* p = this; while (p) if (p->god.name == name) break; else p = p->succ; return p; } template<typename T> const Link<T>* Link<T>::find(const string& name) const //在const链表中查找s { const Link<T>* p = this; while (p) if (p->god.name == name) break; else p = p->succ; return p; } template<typename T> Link<T>* Link<T>::advance(int n) //在链表中移动n个位置 { Link<T>* p = this; if (n < 0) { while (n++) p = p->pred; } else if (n > 0) while (n--) p = p->succ; return p; } //辅助函数 template<typename T> void print_all(Link<T>* p) { cout << "{ "; God g; while (p) { g = p->god; cout << "( " << g.name << ", " << g.mythology << ", " << g.mount << ", " << g.weapon << " )"; if (p = p->next()) cout << '\n'; } cout << " }"; }
//Exercise 14.5, 14.6 and 14.7 #include"../../std_lib_facilities.h" template<typename T> //T应是数值类型 class Number { T n; public: Number(T ini = T{}) :n{ ini } { } T get() const { return n; } void set(T v) { n = v; } Number& operator=(const Number& a); //赋值运算符必须重载为类的非静态成员函数 }; template<typename T> Number<T>& Number<T>::operator=(const Number<T>& a) { n = a.get(); return *this; } //二元运算符重载,如果不改变左操作数,那么一般重载为非成员函数 template<typename T> Number<T> operator+(const Number<T>& a, const Number<T>& b) { Number<T> res{ a.get() + b.get() }; return res; } template<typename T> Number<T> operator+=(Number<T>& a, const Number<T>& b) { a.set(a.get() + b.get()); return Number<T>{a.get()}; } template<typename T> Number<T> operator-(const Number<T>& a, const Number<T>& b) { Number<T> res { a.get() - b.get() }; return res; } template<typename T> Number<T> operator*(const Number<T>& a, const Number<T>& b) { Number<T> res { a.get()* b.get() }; return res; } template<typename T> Number<T> operator/(const Number<T>& a, const Number<T>& b) { if (b.get() == 0) error("divide by zero"); Number<T> res { a.get() / b.get() }; return res; } template<typename T> Number<T> operator%(const Number<T>& a, const Number<T>& b) { if (b.get() == 0) error("mod by zero"); //模运算可定义为 x % y = x - int(x / y) * y T res = a.get() - int(a.get() / b.get()) * b.get(); return Number<T> {res}; } template<typename T> istream& operator>>(istream& is, Number<T>& n) { T v; is >> v; n.set(v); return is; } template<typename T> ostream& operator<<(ostream& os, const Number<T>& n) { os << n.get(); return os; } //专门针对习题7的乘法模板 template<typename T, typename U> Number<T> operator*(const Number<T>& a, const Number<U>& b) { Number<T> res{ a.get() * b.get() }; return res; } //template<typename T, typename U> //T in_product(const vector<T>& vt, const vector<U>& vu); //VS2019仍然要求在使用模板的地方必须能够得到模板的完整定义,所以上面的声明是不行的,必须得是下面的完整定义 template<typename T, typename U> //T和U的限制为可以做乘法和加法的类型 T in_product(const vector<T>& vt, const vector<U>& vu) { T res{ 0 }; if (vt.size() != vu.size()) { cerr << "two vectors have different size\n"; return res; } for (size_t i = 0; i < vt.size(); ++i) res += vt[i] * vu[i]; return res; } int main() try { Number<int>a{ 1 }; Number<int>b; cout << "int a = " << a << '\n'; a = Number<int>{ 72 }; cout << "a = Number<int>{ 72 } : a = " << a << '\n'; cout << "int b = " << b << '\n'; cin >> b; cout << "cin >> b --> int b = " << b << '\n'; cout << "a + b = " << a + b << '\n'; cout << "a - b = " << a - b << '\n'; cout << "a * b = " << a * b << '\n'; cout << "a / b = " << a / b << '\n'; cout << "a % b = " << a % b << '\n'; Number<double>x{ 1.2 }; Number<double>y; cout << "double x = " << x << '\n'; cout << "double y = " << y << '\n'; x = Number<double>{ 7.2 }; cout << "x = Number<double>{ 7.2 } --> x = " << x << '\n'; cin >> y; cout << "cin >> y --> double y = " << y << '\n'; cout << "x + y = " << x + y << '\n'; cout << "x - y = " << x - y << '\n'; cout << "x * y = " << x * y << '\n'; cout << "x / y = " << x / y << '\n'; cout << "x % y = " << x % y << '\n'; vector<Number<double>>vt{ x, y }; vector<Number<int>>vu{ a, b }; Number<double> res = in_product(vt, vu); cout << "vt .* vu = " << res << '\n'; return 0; } catch (runtime_error& e) { cerr << "Runtime error: " << e.what() << endl; return 1; } catch (...) { cerr << "Exception occured!\n"; return 2; }
14_8-Allocator.h
//14_8-Allocator.h #include<iostream> #include<stdio.h> #include<stdlib.h> using std::cerr; template<typename T>class allocator { public: allocator() {} T* allocate(int n); //为n个类型为T的对象分配空间 void deallocate(T* p, int n); //释放从p开始的n个类型为T的对象 void construct(T* p, const T& v); //在地址p构造一个值为v的T类型对象 void destroy(T* p); //销毁p中的T }; template<typename T> T* allocator<T>::allocate(int n) { T* p = (T*)malloc(n * sizeof(T)); if (p == NULL) { fprintf(stderr, "allocating fail\n"); return nullptr; } return p; } template<typename T> void allocator<T>::deallocate(T* p, int n) { if (n < 0) { cerr << "deallocate fail: n can not be negative\n"; return; } if (n == 0) return; free(p); } template<typename T> void allocator<T>::construct(T* p, const T& v) { new (p) T{ v }; } template<typename T> void allocator<T>::destroy(T* p) { p->~T(); }
template<typename T, typename A> vector<T, A>& vector<T, A>::operator=(const vector& arg) { if (this == &arg) //自赋值,什么也不用做 ; else if (arg.sz <= space) //空间足够,无需分配空间 { for (int i = 0; i < sz; ++i) alloc.destroy(elem + i); //先销毁原来的元素 for (int i = 0; i < arg.sz; ++i) alloc.construct(&elem[i], arg.elem[i]); //拷贝元素 sz = arg.sz; } else { T* p = alloc.allocate(arg.sz); for (int i = 0; i < arg.sz; ++i) alloc.construct(p + i, arg.elem[i]); //拷贝元素 alloc.deallocate(elem, space); sz = space = arg.sz; //设置新大小 elem = p; //指向新元素的指针 } return *this; //按照惯例,赋值运算符将返回被赋值对象的引用 }
非常简单的一个 unique_ptr 实现,虽然没有实现其赋值操作或拷贝构造函数,但是不知道怎么阻止其默认拷贝操作,所以默认的赋值操作仍然可以运行的。。。
#include<iostream> #include<vector> using std::cout; using std::cerr; using std::endl; using std::vector; template<class T> class unique_ptr { public: explicit unique_ptr(T* p) :pobj{ p } { } T& operator*(); T* operator->(); T* release(); ~unique_ptr() { delete pobj; } private: T* pobj; }; template<class T> T& unique_ptr<T>::operator*() { return *pobj; } template<class T> T* unique_ptr<T>::operator->() { return pobj; } template<class T> T* unique_ptr<T>::release() { T* temp = pobj; pobj = nullptr; return temp; } void is_free() { //调用这个函数,使用vs2019的诊断工具的堆分析查看调用前后的堆情况 unique_ptr<double>pdarr{ new double[5]{0.0,1.1,2.2,3.3,4.4} }; } vector<int>* test_vector() { unique_ptr<vector<int>> pv{ new vector<int> }; cout << "unique_ptr<vector<int>> pv{ new vector<int> }; pv->size = " << pv->size() << endl; cout << "pv->push_back(i)...\n"; for (size_t i = 0; i < 10; ++i) pv->push_back(i); cout << "After push_back:\n"; for (int x : *pv) cout << x << ' '; cout << endl; return pv.release(); } void test_release() { vector<int>* pv = test_vector(); cout << "vector<int>* pv = test_vector(); element of pv:\n"; for (int x : *pv) cout << x << ' '; cout << endl; delete pv; } int main() try { unique_ptr<double> pd{ new double {5.5} }; cout << "unique_ptr<double> pd{ new double {5.5} } --> *pd = " << *pd << endl; *pd = 6.6; cout << "*pd = 6.6; --> *pd = " << *pd << endl; is_free(); test_release(); return 0; } catch (...) { cerr << "Exception occured!\n"; return 2; }
#include<iostream> #include<vector> using std::cout; using std::cerr; using std::endl; using std::vector; template<class T> class counted_ptr { public: explicit counted_ptr(T ini = T{}); //构造函数,在自由存储区中为T对象和其“使用计数”分配空间,并给T对象设置初始值ini counted_ptr(const counted_ptr&); //拷贝构造函数 counted_ptr& operator=(const counted_ptr&); //拷贝赋值 T& operator*(); T* operator->(); ~counted_ptr(); private: T* pobj; int* pcnt; //指向“使用计数”的指针 }; template<class T> counted_ptr<T>::counted_ptr(T ini) :pobj{ new T {ini} }, pcnt{ new int {1} } { } template<class T> counted_ptr<T>::counted_ptr(const counted_ptr& cp) :pobj{cp.pobj},pcnt{cp.pcnt} { ++(*pcnt); } template<class T> counted_ptr<T>& counted_ptr<T>::operator=(const counted_ptr& cp) { if (this == &cp || pobj == cp.pobj) //自赋值或者被赋值为已经指向的对象的计数指针,什么也不需要做 return *this; if (pcnt && --(*pcnt) <= 0) //如果它是最后一个指向T对象的计数指针 { delete pobj; delete pcnt; } pobj = cp.pobj; pcnt = cp.pcnt; ++(*pcnt); return *this; } template<class T> T& counted_ptr<T>::operator*() { return *pobj; } template<class T> T* counted_ptr<T>::operator->() { return pobj; } template<class T> counted_ptr<T>::~counted_ptr() { if (--(*pcnt) == 0) { delete pobj; delete pcnt; } } template<class T> void is_free(counted_ptr<T> cp) { //调用这个函数,使用vs2019的诊断工具的堆分析查看调用前后的堆情况 counted_ptr<double>pdarr; } template<class T> counted_ptr<vector<int>> test_vector(counted_ptr<T> cp) { counted_ptr<vector<int>> pv{ vector<int>{} }; cout << "counted_ptr<vector<int>> pv{ new vector<int> }; pv->size = " << pv->size() << endl; cout << "pv->push_back(i)...\n"; for (size_t i = 0; i < 10; ++i) pv->push_back(i); cout << "After push_back:\n"; for (int x : *pv) cout << x << ' '; cout << endl; return pv; } template<class T> void test_release(counted_ptr<T>& cp) { counted_ptr<vector<int>> pv = test_vector(cp); cout << "vector<int>* pv = test_vector(); element of pv:\n"; for (int x : *pv) cout << x << ' '; cout << endl; } int main() try { counted_ptr<double> pd {5.5}; cout << "counted_ptr<double> pd{ new double {5.5} } --> *pd = " << *pd << endl; *pd = 6.6; cout << "*pd = 6.6; --> *pd = " << *pd << endl; is_free(pd); test_release(pd); return 0; } catch (...) { cerr << "Exception occured!\n"; return 2; }
这题的测试我不太会
#include"../../std_lib_facilities.h" class File_handle { public: explicit File_handle(const string&); ~File_handle() { fs.close(); } template<class T> fstream& operator>>(T&); template<class T> fstream& operator<<(T&); private: fstream fs; }; File_handle::File_handle(const string& fname) :fs{fname, ios_base::in|ios_base::out} { if (!fs) error("can't open file ", fname); } template<class T> fstream& File_handle::operator>>(T& idata) { fs >> idata; return fs; } template<class T> fstream& File_handle::operator<<(T& odata) { fs << odata; if (!fs) error("can't output ", odata); return fs; } int main() try { string fname{ "14_12.txt" }; File_handle fh(fname); //我的现有知识发现,对于文件流来说,要么读,要么写,做不到先写再读或者先读再写 //或许可以显式刷新流,做到先写再读或者先读再写 double odata{ 1.0 }; fh << odata; /*string idata; fh >> idata; cout << "input data from " << fname << ": " << idata;*/ return 0; } catch (runtime_error& e) { cerr << "Runtime error: " << e.what() << endl; return 1; }
#include"../../std_lib_facilities.h" class Tracer { public: explicit Tracer(const string& s) :str{ s } { cout << "Tracer: " << s << endl; } ~Tracer() { cout << "~Tracer: " << str << endl; } Tracer(const Tracer&); Tracer& operator=(const Tracer&); private: string str; }; Tracer::Tracer(const Tracer& tr) :str{tr.str} { cout << "Tracer Copy Construction: " << str << endl; } Tracer& Tracer::operator=(const Tracer& tr) { cout << "Tracer Copy assignment old string: " << str << endl; str = tr.str; cout << "Tracer Copy assignment: " << str << endl; return *this; } //测试部分 class Test_class { Tracer m_obj; //类内成员对象 public: Test_class() :m_obj{"Member object of Test_class"}{ } Test_class& operator=(const Test_class&); }; Test_class& Test_class::operator=(const Test_class& tc) { cout << "Test_class Copy Assignment: \n"; m_obj = tc.m_obj; return *this; } Tracer func_call(Tracer& tr); Tracer g_obj{ "Global object" }; //全局对象 int main() { Tracer loc_obj1{ "Local object 1" }; //局部对象1 Tracer loc_obj2{ "Local object 2" }; //局部对象2 Tracer loc_obj3{ func_call(loc_obj2) }; //局部对象3 loc_obj2 = loc_obj1; Tracer* fs_obj = new Tracer{ "Free stroe object" }; //自由空间分配的对象 Test_class tc1; //测试类内成员对象 Test_class tc2; //测试类内成员对象 tc2 = tc1; delete fs_obj; //释放对象 return 0; } Tracer func_call(Tracer& tr) { Tracer loc_obj3{ tr }; return loc_obj3; }
这题没怎么测试,可能会有潜在的bug
//和书上不一样的vector_base #include<iostream> template<typename T> struct vector_base { static const int first_expand_space{ 8 }; int sz; int space; T* elem; vector_base() :sz{ 0 }, space{ 0 }, elem{ nullptr }{} vector_base(int n, T ini); vector_base(std::initializer_list<T>lst); //初始化器列表构造函数 vector_base(const vector_base& arg); //拷贝构造函数 vector_base& operator=(const vector_base& arg); //拷贝赋值函数 ~vector_base() { delete[] elem; } void reserve(int newalloc); void resize(int newsize, T ini); void push_back(const T& val); }; template<typename T> vector_base<T>::vector_base(int n, T ini) :sz{ n }, space{ n }, elem{ new T[n] } { for (int i = 0; i < n; ++i) elem[i] = ini; } template<typename T> vector_base<T>::vector_base(std::initializer_list<T> lst) //初始化器列表构造函数 :sz{ int(lst.size()) }, space{ int(lst.size()) }, elem{ new T[lst.size()] } { //std::cout << "初始化列表构造函数\n"; std::copy(lst.begin(), lst.end(), elem); //初始化 } template<typename T> vector_base<T>::vector_base(const vector_base& arg) //拷贝构造函数 : sz{ arg.sz }, space{ arg.sz }, elem{ new T[arg.sz] } { //std::cout << "拷贝构造函数\n"; std::copy(arg.elem, arg.elem + arg.sz, elem); } template<typename T> vector_base<T>& vector_base<T>::operator=(const vector_base& arg) //拷贝赋值函数 { //std::cout << "拷贝赋值函数\n"; if (this == &arg) //自赋值,什么也不用做 ; else if (arg.sz <= space) //空间足够,无需分配空间 { for (int i = 0; i < arg.sz; ++i) elem[i] = arg.elem[i]; //拷贝元素 sz = arg.sz; } else { T* p = new T[arg.sz]; std::copy(arg.elem, arg.elem + arg.sz, p);//拷贝元素 delete[] elem; sz = space = arg.sz; //设置新大小 elem = p; //指向新元素的指针 } return *this; //按照惯例,赋值运算符将返回被赋值对象的引用 } template<typename T> void vector_base<T>::reserve(int newalloc) { if (newalloc <= space) //永远不会减少分配的空间 return; T* p = new T[newalloc]; //分配新空间 std::copy(elem, elem + sz, p); //拷贝现有元素 delete[] elem; //释放旧空间 elem = p; space = newalloc; } template<typename T> void vector_base<T>::resize(int newsize, T ini) //令 vector_base 有 newsize 个元素 //newsize 必须 >= 0 //用默认值 ini 初始化每个新元素 { reserve(newsize); for (int i = sz; i < newsize; ++i) elem[i] = ini; //用默认值初始化 sz = newsize; } template<typename T> void vector_base<T>::push_back(const T& val) //将 vector 的大小增加1:用 val 初始化新元素 { if (space == 0) reserve(first_expand_space); else if (sz >= space) reserve(space * 2); elem[sz] = val; ++sz; } //下面是封装的Vector template<typename T> class vector { public: class Invalid {}; struct out_of_range { /*...*/ }; //用来报告越界错误 vector() :pvb{ nullptr } {} vector(int n, T ini = T{}); vector(std::initializer_list<T> lst) :pvb{ new vector_base<T>{lst} }{} //初始化器列表构造函数 vector(const vector& arg) : pvb{ new vector_base<T>{*arg.pvb} } {} //拷贝构造函数 vector& operator=(const vector&); //拷贝赋值函数 vector(vector&&); //移动构造函数 vector& operator=(vector&&); //移动赋值函数 ~vector() { delete pvb; } int size() const; void reserve(int newalloc); //改变 space 的大小 int capacity()const; //返回 space 的大小 void resize(int newalloc, T ini = T{}); //该表元素数量 void push_back(const T& val); T& operator[](int n); const T& operator[](int n) const; T& at(int n); const T& at(int n) const; private: vector_base<T>* pvb; }; template<typename T> vector<T>::vector(int n, T ini) { if (n <= 0) pvb = nullptr; else pvb = new vector_base<T>(n, ini); } template<typename T> vector<T>& vector<T>::operator=(const vector& arg) //拷贝赋值函数 { //std::cout << "拷贝赋值函数\n"; if (this != &arg) //如果是自赋值,什么也不用做 { if (pvb == nullptr) pvb = new vector_base<T>{ *arg.pvb }; else *pvb = *(arg.pvb); } return *this; //按照惯例,赋值运算符将返回被赋值对象的引用 } template<typename T> vector<T>::vector(vector&& arg) //移动构造函数 :pvb{ arg.pvb } { //std::cout << "移动构造函数\n"; arg.pvb = nullptr; } template<typename T> vector<T>& vector<T>::operator=(vector&& arg) //移动赋值函数,将 arg 移动到本vector { //std::cout << "移动赋值函数\n"; delete pvb; pvb = arg.pvb; arg.pvb = nullptr; return *this; } template<typename T> int vector<T>::size() const { if (pvb == nullptr) return 0; else return pvb->sz; } template<typename T> void vector<T>::reserve(int newalloc) { if (newalloc <= 0) return; if (pvb == nullptr) pvb = new vector_base<T>(); pvb->reserve(newalloc); } template<typename T> int vector<T>::capacity() const { return pvb->space; } template<typename T> void vector<T>::resize(int newsize, T ini) //令 vector 有 newsize 个元素 //newsize 必须 >= 0 //用默认值 ini 初始化每个新元素 { if (newsize < 0) throw Invalid{}; if (newsize == 0 && pvb == nullptr) return; else if (pvb == nullptr) pvb = new vector_base<T>(); pvb->resize(newsize, ini); } template<typename T> void vector<T>::push_back(const T& val) //将 vector 的大小增加1:用 val 初始化新元素 { if (pvb == nullptr) pvb = new vector_base<T>(); pvb->push_back(val); } template<typename T> T& vector<T>::operator[](int n) { return pvb->elem[n]; } template<typename T> const T& vector<T>::operator[](int n) const { return pvb->elem[n]; } template<typename T> T& vector<T>::at(int n) { if (n < 0 || pvb->sz <= n) throw out_of_range(); return pvb->elem[n]; } template<typename T> const T& vector<T>::at(int n) const { if (n < 0 || pvb->sz <= n) throw out_of_range(); return pvb->elem[n]; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。