重写C++中的Vector

Vector的一种实现

注意几点:

分配内存不要使用new和delete,因为new的同时就把对象构造了,而我们需要的是原始内存。

所以应该使用标准库提供的allocator类来实现内存的控制。当然也可以重载operator new操作符,因为二者都是使用malloc作为底层实现,所以直接采用malloc也可以。

对象的复制必须使用系统提供的uninitialized_fill和uninitialized_copy,因为我们无法手工调用构造函数。

对于C++中的对象,除了POD之外,使用memcpy系列的函数是绝对错误的。

代码如下:

#ifndef VECTOR_H_
#define VECTOR_H_

#include <stddef.h>
#include <algorithm>
#include <memory>

template <typename T>
class Vector
{
public:
    typedef T *iterator;
    typedef const T *const_iterator;
    typedef size_t size_type;
    typedef T value_type;

    Vector() { create(); }
    explicit Vector(size_type n, const T &t = T())  { create(n, t); }
    Vector(const Vector &v) { create(v.begin(),  v.end()); }
    ~Vector() { uncreate(); }

    Vector &operator=(const Vector &other);
    T &operator[] (size_type i) { return data_[i]; }
    const T &operator[] (size_type i) const { return data_[i]; }

    void push_back(const T &t);

    size_type size() const { return avail_ - data_; }
    size_type capacity() const { return limit_ - data_; }

    iterator begin() { return data_; }
    const_iterator begin() const { return data_; }
    iterator end() { return avail_; }
    const_iterator end() const { return avail_; }

private:
    iterator data_; //首元素
    iterator avail_; //末尾元素的下一个位置
    iterator limit_; //内存的后面一个位置

    std::allocator<T> alloc_; //内存分配器

    void create();
    void create(size_type, const T &);
    void create(const_iterator, const_iterator);

    void uncreate();

    void grow();
    void uncheckedAppend(const T &);
};

template <typename T>
Vector<T> &Vector<T>::operator=(const Vector &rhs)
{
    if(this != &rhs)
    {
        uncreate(); //释放原来的内存
        create(rhs.begin(), rhs.end());
    }

    return *this;
}

template <typename T>
void Vector<T>::push_back(const T &t)
{
    if(avail_ == limit_)
    {
        grow();
    }
    uncheckedAppend(t);
}

template <typename T>
void Vector<T>::create()
{
    //分配空的数组
    data_ = avail_ = limit_ = 0;
}

template <typename T>
void Vector<T>::create(size_type n, const T &val)
{
    //分配原始内存
    data_ = alloc_.allocate(n);
    limit_ = avail_ = data_ + n;
    //向原始内存填充元素
    std::uninitialized_fill(data_, limit_, val);
}

template <typename T>
void Vector<T>::create(const_iterator i, const_iterator j)
{
    data_ = alloc_.allocate(j-i);
    limit_ = avail_ = std::uninitialized_copy(i, j, data_);
}

template <typename T>
void Vector<T>::uncreate()
{
    if(data_)
    {
        //逐个进行析构
        iterator it = avail_;
        while(it != data_)
        {
            alloc_.destroy(--it);
        }

        //真正的释放内存
        alloc_.deallocate(data_, limit_ - data_);
    }
    //重置指针
    data_ = limit_ = avail_ = 0;
}

template <typename T>
void Vector<T>::grow()
{
    //内存变为两倍
    size_type new_size = std::max(2 * (limit_ - data_), std::ptrdiff_t(1));
    //分配原始内存
    iterator new_data = alloc_.allocate(new_size);
    //复制元素
    iterator new_avail = std::uninitialized_copy(data_, avail_, new_data);

    uncreate(); //释放以前的内存,以及析构元素

    data_ = new_data;
    avail_ = new_avail;
    limit_ = data_ + new_size;
}

template <typename T>
void Vector<T>::uncheckedAppend(const T &val)
{
    alloc_.construct(avail_++, val);
}

#endif  /* VECTOR_H_ */

测试代码如下:

#include "Vector.hpp"
#include <iostream>
#include <string>
using namespace std;

int main(int argc, char const *argv[])
{
    Vector<string> vec(3, "hello");

    for(Vector<string>::const_iterator it = vec.begin();
        it != vec.end();
        ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    cout << "size = " << vec.size() << endl;
    cout << "capacity = " << vec.capacity() << endl;
    vec.push_back("foo");
    vec.push_back("bar");

    cout << "size = " << vec.size() << endl;
    cout << "capacity = " << vec.capacity() << endl;

    return 0;
}
时间: 2024-12-18 13:08:17

重写C++中的Vector的相关文章

实战c++中的vector系列--再谈vector的insert()方法(都是make_move_iterator惹的祸)

之前说过了关于vector的insert()方法,把vector B的元素插入到vector A中,vector A中的结果我们可想而知,但是vector B中的元素还会如何? 看看之前写过的程序: #include <iostream> #include <vector> int main () { std::vector<int> myvector (3,100); std::vector<int>::iterator it; it = myvector

STL中的Vector相关用法

STL中的Vector相关用法 标准库vector类型使用需要的头文件:#include <vector>. vector 是一个类模板,不是一种数据类型,vector<int>是一种数据类型. Vector的存储空间是连续的,list不是连续存储的. 1. 定义和初始化 vector< typeName > v1; //默认v1为空,故下面的赋值是错误的v1[0]=5;//v2是v1的一个副本,若v1.size()>v2.size()则赋值后v2.size()被

什么情况下才要重写Objective-C中的description方法

特别注意: 千万不要在description方法中同时使用%@和self,同时使用了%@和self,代表要调用self的description方法,因此最终会导致程序陷入死循环,循环调用description方法 1.NSLog回顾   大家都知道,我们可以用NSLog函数来输出字符串和一些基本数据类 1 int age = 11; 2 NSLog( @" age is %d", age); * 第2行的%d代表会输出一个整型数据,右边的变量age会代替%d的位置进行输出 * 输出结果

备忘: C++中的 vector 容器

在C++ 中使用 vector:容器或叫向量.对用来管理不定长度的数据集或经常变化的数据组,很方便.可以简单的理解他是一种数据组,一种数据类型的集合. vector是同一种类型的对象的集合.它相当于一个动态的数组, 当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间的目的. 使用vector首先要在程序开头处加上头文件,并使用其命名 : #include <vector> using std::vector; vector的声明与初始化: vector <类型

c++ STL中的vector与list为什么没有提供find操作?

map里有,set里也有,vector,list没有,太不公平了吧. 其实应该考虑为什么map,set里有find操作. include<algorithm>里有通用的find操作,通用的find内部是从begin到end进行一次遍历,复杂度是O(n). 通过iterator从begin到end遍历map与set时,得到的结果是按key排序的结果,而不是插入时的顺序(所以这两个容器没有push_back操作), 其实,insert到map与set中的元素会被组织到一颗红黑树上,红黑树是一颗平衡

c++中的vector原理

vectorvector就是动态数组.它也是在堆中分配内存,元素连续存放,有保留内存,如果减少大小后,内存也不会释放.如果新值>当前大小时才会再分配内存. 它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随即存取,即[]操作符,但由于它的内存空间是连续的,所以在中间进行插入和删除会造成内存块的拷贝,另外,当该数组后的内存空间不够时,需要重新申请一块足够大的内存并进行内存的拷贝.这些都大大影响了vector的效率.对最后元素操作最快(在后面添加删除最快 ), 此时一般不需要移动内存

C++ vector中实际删除元素使用的是容器vecrot中std::vector::erase()方法

C++ vector中实际删除元素使用的是容器vecrot中std::vector::erase()方法. C++ 中std::remove()并不删除元素,因为容器的size()没有变化,只是元素的替换. 1.std::vector::erase() 函数原型:iterator erase (iterator position); //删除指定元素 iterator erase (iterator first, iterator last); //删除指定范围内的元素 返回值:指向删除元素(或

地址重写--Java中urlrewriter的使用

最近公司以前的一个项目需要升级改版,其中的一个模块是使用Struts2做的不需要改动,但是需要将其从之前的项目里面剥离出来,看了看官网,发现所有的链接访问的静态地址,以为是FreeMarker实现的,仔细研究了会发现不是那么回事,原来是伪静态,程序使用了urlrewriter.其实urlrewriter的使用很简单,看看下面你就明白了. urlrewriter简介:url rewrite将我们的动态网页地址转化为静态的地址,如html.shtml,还可以隐藏网页的真正路径,比如:有时候需要将xx

C/C++中容器vector使用方法&lt;第二弹&gt;

此文总结常用vector操作,是前一篇的续作!只有代码,详细请看代码中的注释.出于反爬虫的目的,你不是在http://blog.csdn.net/zhanh1218上看到的,肯定不是最新最全的. /********************************************************************* * file_name: vector_test.cpp * * Created on: 2014年6月28日 下午3:34:23 * Author: The_T