个人主页:仍有未知等待探索-CSDN博客
专题分栏:C++
请多多指教!
目录
vector就是一个支持变长的数组。
vector的使用不做过多强调,注重的是实现vector类。
可以点击下面的链接进入cplusplus网站,查看文档。
- #include
- #include
- #include
- #include
- using namespace std;
-
- template<class T>
- class vector
- {
- public:
- typedef T* iterator;//普通迭代器
- typedef const T* const_iterator;//const迭代器
- // Iterators:
- iterator begin()
- {
- return _start;
- }
- iterator end()
- {
- return _finish;
- }
- const_iterator begin() const
- {
- return _start;
- }
- const_iterator end() const
- {
- return _finish;
- }
- // 成员函数
- private:
- iterator _start = nullptr;
- iterator _finish = nullptr;
- iterator _endofstorage = nullptr;
- };
- // 无参的构造必须写,因为下面实现了构造函数,编译器不会自动生成一个无参构造函数
- vector(){}
- // 开辟n个大小的空间,并初始化为m
- vector(const int& n, const int& m = 0)
- {
- // 新写法(复用reserve)
- reserve(n);
- for (int i = 0; i < n; i ++ ) _start[i] = m;
- _finish = _start + n;
- }
- // 用迭代器进行构造
- template<class input_iterator>
- vector(input_iterator start, input_iterator end)
- {
- input_iterator it = start;
- while (it != end)
- {
- push_back(*it);
- it ++ ;
- }
- }
- // 开辟n个大小的空间,并初始化为val
- // const T& val = T() -> 用一个匿名对象进行初始化,目的是为了预防vector
中T是一个自定义类型。 - vector(size_t n, const T& val = T())
- {
- resize(n, val);// 复用resize
- }
- // 用一个vector
进行拷贝构造 - vector(const vector
& v) - {
- reserve(v.capacity());
- for (auto& e : v)
- {
- // 复用push_back()
- push_back(e);
- }
- }
- // 用列表进行初始化
- // vector
v = {1, 2, 3}; - // 用库函数实现的initializer_list
- vector(initializer_list
il) - {
- reserve(il.size());
- for (auto& e : il)
- {
- push_back(e);
- }
- }
- // 析构函数
- ~vector()
- {
- delete[] _start;
- _start = _finish = _endofstorage = nullptr;
- }
- vector
& operator=(vector v) - {
- swap(v);
- return *this;
- }
- // Capacity:
- size_t capacity() const
- {
- return _endofstorage - _start;
- }
- size_t size() const
- {
- return _finish - _start;
- }
- bool empty() const
- {
- return size() == 0;
- }
- void reserve(size_t n)
- {
- if (capacity() < n)
- {
- T* tmp = new T[n];
- int old_size = size();
- //memcpy(tmp, _start, size() * sizeof(T));
- // 当T是string类型的时候,memcpy会导致浅拷贝问题,并且会同时对一块空间析构多次
- for (int i = 0; i < old_size; i ++ )
- {
- tmp[i] = _start[i];
- }
- delete[] _start;
-
- _start = tmp;
- _finish = tmp + old_size;
- _endofstorage = tmp + n;
- }
- }
- void resize(size_t n, const T& val = T())
- {
- reserve(n);
- iterator it = _start;
- while (it != _endofstorage)
- {
- *it = val;
- it ++ ;
- }
- }
- // Element access:
- T& operator[](int pos)
- {
- assert(pos < size());
- return _start[pos];
- }
-
- // Modifiers:
- // 在pos之前插入一个数x
- void insert(iterator pos, const T& x)
- {
- assert(pos >= _start);
- assert(pos <= _finish);
- if (_finish == _endofstorage)
- {
- int len = pos - _start;
- reserve(capacity() == 0 ? 4 : 2 * capacity());
- pos = _start + len;
- }
- iterator it = _finish - 1;
- while (it >= pos)
- {
- *(it + 1) = *it;
- it -- ;
- }
- *pos = x;
- _finish ++ ;
- }
- // 尾插
- void push_back(const T& x)
- {
- // 老写法
- /*if (_finish == _endofstorage)
- {
- reserve(capacity() == 0 ? 4 : 2 * capacity());
- }
- *_finish = x;
- _finish ++ ;*/
- // 新写法
- insert(end() , x);
- }
- // 尾删
- void pop_back()
- {
- assert(!empty());
- _finish -- ;
- }
- // 交换函数,用库里面的swap实现指针的交换,来完成vector的交换
- void swap(vector
& v) - {
- std::swap(_start, v._start);
- std::swap(_finish, v._finish);
- std::swap(_endofstorage, v._endofstorage);
- }
如果要将一个引用进行赋值,并且没有对赋值运算符重载的话,会只进行值拷贝而导致浅拷贝。最后会使编译器对同一块空间析构多次。
为什么*pos,x都是T类型的,而赋值重载却写一个vector
类型的就能行? 因为单参数的构造函数支持隐式类型转化,编译器会先进行构造函数,将这两个值构造成对象,然后在进行赋值。
- vector
& operator=(vector v) - {
- swap(v);
- return *this;
- }
需要在使用这个类型前面加上typename标志这是一个类型。
- template<class T>
- void print_vector(vector
& v) - {
- // 不加typename会报错,因为在这个函数模板里,vector
这个类并没有实例化,会不清楚const_iterator是类型还是变量 - // 加typename的含义就是告诉编译器,这个是类型
- typename vector
::const_iterator it = v.begin(); - //auto it = v.begin();
- while (it != v.end())
- {
- cout << *it << " ";
- it ++ ;
- }
- }
这个错误的原因是类模板或函数模板里面有语法错误。(比如说少加了一个分号等等)