C++对象运算符重载,容器迭代器

2022/2/2 20:13:05

本文主要是介绍C++对象运算符重载,容器迭代器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

+,++, += 、其他的运算符重载函数差不多,以及输出out,输入 in

#include <iostream>
using namespace std; 
/* 
C++ 运算符重载:使对象的运算表现得和编译器内置类型一样
template<typename T>
T sum(T a, T b)
{
    return a+ b; //a.+(b)
}

1.编译器做对象运算的时候,会调用对象的运算符重载函数(优先调用成员方法);如果没有成员方法
    就在全局作用域找合适的运算符重载函数,如果没有就会报全局没有合适的方法
*/
class CComplex
{
    public:
        CComplex(int r = 0, int i = 0)
            :mreal(r),mimage(i)
        {}
        CComplex operator+(const CComplex &src)
        {
            // CComplex temp;
            // temp.mimage = this->mimage + src.mimage;
            // temp.mreal  = this->mreal  + src.mreal;
            // return temp;
            return CComplex(this->mreal + src.mreal,this->mimage + src.mimage);
        }
        void show() const 
        {
            cout << "real:" << mreal<<", image:" << mimage << endl;
        }

        CComplex operator++(int) //后置对象是先赋值然后再给自身的对象加
        {
            // CComplex comp = *this;
            // mreal += 1;
            // mimage += 1;
            // return comp;
            return CComplex(mreal ++, mimage ++);
        }
        CComplex& operator++() //前置++ 
        {
            mreal += 1;
            mimage += 1;
            return *this;
        }
        void operator+=(const CComplex &src)
        {
            mreal += src.mreal;
            mimage += src.mimage;
        }
    private:
        int mreal;
        int mimage;
        friend CComplex operator+(const CComplex &lhs, const CComplex &rhs);
        friend ostream& operator<<(ostream &cout , const CComplex & src);
        friend istream& operator>>(istream& in, CComplex &src);
};

CComplex operator+(const CComplex &lhs, const CComplex &rhs)
{
    //不能直接访问私有变量,但是可以把这个重载函数设置为友元函数
    return CComplex(lhs.mreal+rhs.mreal, lhs.mimage + rhs.mimage);
}
//
ostream& operator<<(ostream &out , const CComplex & src)
{
    out << "real:" << src.mreal<<", image:" << src.mimage << endl;
    return out;
}

istream& operator>>(istream& in, CComplex &src)
{
    in >> src.mreal >> src.mimage ;
    return in;
}


int main()
{
    CComplex comp1(10,10);
    CComplex comp2(20,20);
    //comp1.operator+(comp2) 加法运算符重载函数
    CComplex comp3 = comp1 + comp2;
    comp3.show();
    //首先知道的是comp1 是一个对象,然后20强转为complex接受的一个参数,CComplex(20)
    //调用的加法运算重载函数,是可以的
    CComplex comp4 = comp1 + 20;
    //首先是知道的30是个一个整数,并不会转成complex对象,然后调用comp的重载函数,所以是错误的 
    // CComplex comp5 = 30 + comp2;
    //定义一个全局作用域的重载函数就可以
    CComplex comp6 = 30 + comp2;

    // ++ -- 是做单目运算 operator++() operator++(int) 无参数是前++
    //CComplex operator++(int)
    comp6 = comp1 ++; 
    comp1.show(); // real:11, image:11
    comp6.show(); //real:10, image:10
    //以上后置++ ,也就是先赋值之后再给自己加1


    //CComplex operator++()
    comp6 = ++comp1;
    comp1.show();//real:12, image:12
    comp6.show();//real:12, image:12
    //前置++ ,自身先++,然后再赋值
    

    // void comp1.operator+=(comp2)
    comp1 += comp2;
    comp1.show(); 

    //把打印对象的输出写成和内置的打印一样
    //cout ::operator<<(cout, comp1);
    //ostream& operator<<(ostream &out, comp2)
    cout << comp1 ;

    cin >> comp3;
    cout << comp3;


    return 0;
}


 模拟实现C++ string类代码,加法运算符重载的效率不好。

#include <iostream>
#include <cstring>
using namespace std; 

class String
{
    public:
        String(const char*p = nullptr)
        {
            if(p != nullptr)
            {
                _pstr = new char[strlen(p) + 1];
                strcpy(_pstr,p);
            }else
            {
                _pstr = new char[1];
                *_pstr = '\0';
            }
        }

        ~String()
        {
            delete []_pstr;
            _pstr = nullptr;
        }
        String(const String &str)
        {
            _pstr = new char[strlen(str._pstr) + 1];
            int len = strlen(str._pstr) + 1;
            strcpy(_pstr,str._pstr);
        }
        String& operator= (const String &str)
        {
            if(this == &str) return *this;
            delete []_pstr;
            _pstr = new char[strlen(str._pstr) + 1];
            strcpy(_pstr, str._pstr);
            return *this;
        }

        bool operator>(const String &str) const
        {
            return strcmp(_pstr,str._pstr) > 0;
        }
        bool operator<(const String &str) const
        {
            return strcmp(_pstr,str._pstr) < 0;
        }
        bool operator==(const String &str) const
        {
            return strcmp(_pstr,str._pstr) == 0;
        }

        int length()const 
        {
            return strlen(_pstr);
        }

        char& operator[](int index)
        {
            return _pstr[index];
        }

        const char& operator[](int index) const
        {
            return _pstr[index];
        }

        const char* c_str() const 
        {
            return _pstr;
        }


    private:
        char *_pstr;
        friend String operator+(const String &lhs, const String &rhs);
        friend ostream& operator<<(ostream &out, const String &str);
        friend istream& operator>>(istream &in , String &str);

};

String operator+(const String &lhs, const String &rhs){
    char *ptmp = new char[strlen(lhs._pstr) + strlen(rhs._pstr) + 1];
    strcpy(ptmp, lhs._pstr);
    strcat(ptmp,rhs._pstr);
    String tmp(ptmp);
    delete []ptmp;
    return tmp;
}

ostream& operator<<(ostream &out, const String &str)
{
    out << str._pstr;
    return out;
}
istream& operator>>(istream &in , String &str)
{
    in >> str._pstr;
    return in;
}

int main()
{
    String str1;
    String str2 = "aaa";
    String str3 = "bbb";
    String str4 = str2 + str3;
    String str5 = str2 + "ccc";
    String str6 = "ddd" + str2;

    cout << "str6:" << str6 << endl;

    if (str5 > str6) 
        cout << str5 << ">" << str6 << endl; 
    else 
        cout << str5 << "<" << str6 << endl; 

    int len = str6.length();
    for(int i = 0; i < len; i++)
    {
        cout << str6[i] << " ";
    }
    cout << endl;

    return 0;
}

vector容器迭代器iterator的实现

        迭代器的方法有:构造函数,!=,  * , 以及前置加加

#include <iostream>
#include <cstring>
using namespace std;

/**/
//空间适配器
template<typename T>
class Allocator
{
    public:
        T* allocate(size_t size) // 只负责开辟内存
        {
            return (T*)malloc(sizeof(T) * size);
        }
        void deallocate(void *p) // 只负责内存释放
        {
            free(p);
        }
        //在指定开辟好的内存上进行构造,用定位new
        void construct(T *p, const T &val)
        {
            new (p) T(val);
        }
        void destroy(T *p) //负责对象析构
        {
            p->~T(); //调用对象的析构函数 ~T()代表了T类型的析构函数
        }
};


template<typename T, typename Alloc = Allocator<T> > // Alloc 默认使用Allocator
class vector
{
    public:
        //构造
        //空间配置器可以让用户传进来,模板上边就不用 Alloc 那个参数名了
        // vector(int size = 10,const &alloc = Allocator<T>()):_allocator(alloc)
        vector(int size = 10)
        {
            //需要把内存开辟和对象构造分开处理
            // _first = new T[size];
            _first = _allocator.allocate(size);
            _last = _first;
            _end  = _first + size;
        }
        //析构
        ~vector()
        {
            //析构容器有效地元素,然后再释放_first指针指向的堆内存
            // delete []_first;
            for(T *p = _first; p != _last; ++p)
            {
                //把_first指针指向的数组的有效元素进行析构操作
                _allocator.destroy(p); 
            }
            //释放堆上的数组内存
            _allocator.deallocate(_first); 
            _first = _last = _end = nullptr;
        }
        //拷贝构造
        vector(const vector<T> &rhs)
        {
            int size = rhs._end - rhs._first;
            // _first = new T[size];
            _first = _allocator.allocate(size);
            int len = rhs._last - rhs._first;
            for(int i = 0; i < len; ++i)
            {
                // _first[i] = rhs._first[i];
                _allocator.construct(_first+i,rhs._first[i]);
            }
            _last  = _first + len;
            _end   = _first + size;
        }
        //赋值重载
        vector<T>& operator=(const vector<T> &rhs)
        {
            if(this == &rhs) return *this;
            // delete []_first;
            for(T *p = _first; p != _last; ++p)
            {
                //把_first指针指向的数组的有效元素进行析构操作
                _allocator.destroy(p); 
            }
            //释放堆上的数组内存
            _allocator.deallocate(_first); 

            int size = rhs._end - rhs._first;
            int len  = rhs._last - rhs._first;
            // _first = new T[size];
            _first = _allocator.allocate(size);

            for(int i = 0; i < len; ++i)
            {
                // _first[i] = rhs._first[i];
                _allocator.construct(_first+i,rhs._first[i]);
            }
            _last = _first + len;
            _end  = _first + size;
            return *this;
        }
        //向容器末尾添加元素
        void push_back(const T &val)
        {
            if(full()) expand();
            // *_last++ = val;
            //_last 指针指向的内存构造一个值为val的对象
            _allocator.construct(_last,val);
            _last ++;
        }
        //从容器末尾删除元素
        void pop_back()
        {
            if(empty()) return;
            --_last; //不仅仅要把_last指针--,还需要析构删除的元素
            _allocator.destroy(_last);
        }
        //返回容器末尾的值
        T back() const
        {
            return *(_last - 1);
        }
        //检查容器是否满了
        bool full() const {return _last == _end;}
        //检查容器是否为空
        bool empty() const { return _last == _first;}
        //返回容器的个数
        int size() const {return _last - _first;}

        //中括号运算符重载
        T& operator[](int index) 
        {
            if (index < 0 || index >= size()) throw "OutOfRangException";
            return _first[index];
        }

        //#1 迭代器一般实现成容器的嵌套类型
        class iterator
        {
            public:
                iterator(T *ptr = nullptr)
                    :_ptr(ptr)
                {}

                bool operator!= (const iterator &it) const
                {
                    return _ptr!= it._ptr;
                }
                //后置++会产生临时量
                void operator++()
                {
                    _ptr++;
                }
                T& operator*() // int data  = *it; *it =20
                {
                    return *_ptr;
                }

                const T& operator*()const 
                {
                    return *_ptr;
                }

            private:
                T *_ptr;
        };
        //需要给容器提供begin和end方法
        iterator begin() 
        { 
            return iterator(_first);
        }
        iterator end() 
        {
            return iterator(_last);
        }


    private:
        T *_first; // 指向数组起始的位置
        T *_last ; // 指向数组中有效元素的后继位置
        T *_end  ; // 指向数组空间的后继位置
        Alloc _allocator; //定义容器的空间配置器对象

        void expand()
        {
            int size = _end - _first;
            // T *temp = new T[size * 2];
            T *temp = _allocator.allocate(2*size);
            for (int i = 0; i < size; i++)
            {
                // temp[i] = _first[i];
                _allocator.construct(temp+i,_first[i]);
            }
            // delete []_first;
            for(T *p = _first; p != _last; ++p)
            {
                //把_first指针指向的数组的有效元素进行析构操作
                _allocator.destroy(p); 
            }
            //释放堆上的数组内存
            _allocator.deallocate(_first); 

            _first = temp;
            _last = _first + size;
            _end  = _first + size * 2;

        }

};



class Test
{
    public:
        Test(){
            cout << "Test()" << endl;
        }
        Test(const Test &src)
        {
            cout << "Test(const Test &src)" << endl;
        }
        ~Test() 
        {
            cout << "~Test()" << endl;
        }
};

int main()
{
    vector<int> vec;
    for(int i = 0; i < 20; ++i)
    {
        vec.push_back(rand() % 100 + 1);
    }

    int size = vec.size();
    for(int i = 0; i < size; ++i)
    {
        cout << vec[i] << " ";
    }
    cout << endl;

    vector<int>::iterator it = vec.begin();
    for(;it != vec.end(); ++it)
    {
        cout << *it << " ";
    }

    for(int val : vec) //其底层原理,就是通过容器的迭代器来实现容器遍历的
    {
        cout << val << endl;
    }
    cout << endl;
    return 0;
}

容器的迭代器失效问题

1.迭代器为什么会失效?

        a:当容器调用erase方法后,当前位置到容器末尾的元素所有的迭代器全部都失效了

        b:当容器调用insert方法后,当前位置到容器末尾的元素所有的迭代器全部都失效了

        首元素-----> 插入点、删除点 ----->末尾元素

        c.insert来说,如果引起容器内存扩容,原来容器的所有的迭代器就全部失效了

        d.不同容器的迭代器是不能进行比较运算的

2.迭代器失效了,解决的方法:  对插入删除点的迭代器进行更新操作

问题1:删除元素

vector<int> vec;
for(int i = 0; i < 20; ++i)
{
   vec.push_back(rand() % 10 + 1);
}
//把vec容器中的所有的偶数全部删除
auto it = vec.begin();
for(; it != vec.end(); ++it)
{
  if(*it % 2 == 0)
   {
      //第一次调用erase以后,迭代器就失效了
      vec.erase(it);
    }
}

解决方式:

auto it = vec.begin();
while( it != vec.end())
{
    if(*it % 2 == 0)
    {
        //返回新的迭代器,但是后边的元素会往前挪,所以,不能再加加操作了
        it = vec.erase(it);
    }else
    {
        ++it;
    }
}

问题2:某个位置插入元素

//给容器中的所有的偶数前面添加一个小于偶数值1 的数字
auto it = vec.begin();
for(; it != vec.end(); ++it)
{
    if(*it % 2 == 0)
    {
        //这里的迭代器在第一次insert之后,iterator就失效了
        vec.insert(it, *it -1);
    }
}

解决方式:

//给容器中的所有的偶数前面添加一个小于偶数值1 的数字
auto it = vec.begin();
for(; it != vec.end(); ++it)
{
    if(*it % 2 == 0)
    {
        //更新迭代器,记住:插入元素,当前元素的位置以及后边的元素都往后边移,
                    //如果只是++一次的迭代器又会访问到当前元素的,所以需要两次++
        it = vec.insert(it, *it -1);
        ++it;
    }
}

 模仿vector迭代器失效的源码代码:

#include <iostream>
#include <cstring>
using namespace std;

/**/
//空间适配器
template<typename T>
class Allocator
{
    public:
        T* allocate(size_t size) // 只负责开辟内存
        {
            return (T*)malloc(sizeof(T) * size);
        }
        void deallocate(void *p) // 只负责内存释放
        {
            free(p);
        }
        //在指定开辟好的内存上进行构造,用定位new
        void construct(T *p, const T &val)
        {
            new (p) T(val);
        }
        void destroy(T *p) //负责对象析构
        {
            p->~T(); //调用对象的析构函数 ~T()代表了T类型的析构函数
        }
};


template<typename T, typename Alloc = Allocator<T> > // Alloc 默认使用Allocator
class vector
{
    public:
        //构造
        //空间配置器可以让用户传进来,模板上边就不用 Alloc 那个参数名了
        // vector(int size = 10,const &alloc = Allocator<T>()):_allocator(alloc)
        vector(int size = 10)
        {
            //需要把内存开辟和对象构造分开处理
            // _first = new T[size];
            _first = _allocator.allocate(size);
            _last = _first;
            _end  = _first + size;
        }
        //析构
        ~vector()
        {
            //析构容器有效地元素,然后再释放_first指针指向的堆内存
            // delete []_first;
            for(T *p = _first; p != _last; ++p)
            {
                //把_first指针指向的数组的有效元素进行析构操作
                _allocator.destroy(p); 
            }
            //释放堆上的数组内存
            _allocator.deallocate(_first); 
            _first = _last = _end = nullptr;
        }
        //拷贝构造
        vector(const vector<T> &rhs)
        {
            int size = rhs._end - rhs._first;
            // _first = new T[size];
            _first = _allocator.allocate(size);
            int len = rhs._last - rhs._first;
            for(int i = 0; i < len; ++i)
            {
                // _first[i] = rhs._first[i];
                _allocator.construct(_first+i,rhs._first[i]);
            }
            _last  = _first + len;
            _end   = _first + size;
        }
        //赋值重载
        vector<T>& operator=(const vector<T> &rhs)
        {
            if(this == &rhs) return *this;
            // delete []_first;
            for(T *p = _first; p != _last; ++p)
            {
                //把_first指针指向的数组的有效元素进行析构操作
                _allocator.destroy(p); 
            }
            //释放堆上的数组内存
            _allocator.deallocate(_first); 

            int size = rhs._end - rhs._first;
            int len  = rhs._last - rhs._first;
            // _first = new T[size];
            _first = _allocator.allocate(size);

            for(int i = 0; i < len; ++i)
            {
                // _first[i] = rhs._first[i];
                _allocator.construct(_first+i,rhs._first[i]);
            }
            _last = _first + len;
            _end  = _first + size;
            return *this;
        }
        //向容器末尾添加元素
        void push_back(const T &val)
        {
            if(full()) expand();
            // *_last++ = val;
            //_last 指针指向的内存构造一个值为val的对象
            _allocator.construct(_last,val);
            _last ++;
        }
        //从容器末尾删除元素
        void pop_back()
        {
            if(empty()) return;
            //erase(it); verfy(it._ptr, _last);
            verify(_last - 1, _last);
            --_last; //不仅仅要把_last指针--,还需要析构删除的元素
            _allocator.destroy(_last);
        }
        //返回容器末尾的值
        T back() const
        {
            return *(_last - 1);
        }
        //检查容器是否满了
        bool full() const {return _last == _end;}
        //检查容器是否为空
        bool empty() const { return _last == _first;}
        //返回容器的个数
        int size() const {return _last - _first;}

        //中括号运算符重载
        T& operator[](int index) 
        {
            if (index < 0 || index >= size()) throw "OutOfRangException";
            return _first[index];
        }

        //#1 迭代器一般实现成容器的嵌套类型
        class iterator
        {
            public:
                friend class vector<T,Alloc>;
                 
                iterator(vector<T,Alloc> *pvec=nullptr,T *ptr = nullptr)
                    :_ptr(ptr),_pVec(pvec)
                {
                    Iterator_Base *itb = 
                        new Iterator_Base(this,_pVec->_head._next);
                    _pVec->_head._next = itb;
                }

                bool operator!= (const iterator &it) const
                {
                    //检查迭代器的有效性
                    if(_pVec == nullptr || _pVec != it._pVec)
                    {
                        throw "iterator incompatable!";
                    }
                    return _ptr!= it._ptr;
                }
                //后置++会产生临时量
                void operator++()
                {
                    //检查迭代器有效性
                    if(_pVec == nullptr)
                    {
                        throw "iterator invalid!";
                    }
                    _ptr++;
                }
                T& operator*() // int data  = *it; *it =20
                {
                    if(_pVec == nullptr)
                    {
                        throw "iterator invalid!";
                    }
                    return *_ptr;
                }

                const T& operator*()const 
                {
                    return *_ptr;
                }

            private:
                T *_ptr;
                //当前迭代器是哪个容器对象
                vector<T,Alloc> *_pVec;
        };


        //检查迭代器失效
        void verify(T *first, T *last)
        {
            Iterator_Base *pre = &this->_head;
            Iterator_Base *it  = this->_head._next;
            while(it != nullptr)
            {
                if(it->_cur->_ptr > first && it ->_cur->_ptr <= last)
                {
                    //迭代器失效,把iterator持有的容器指针置为nullptr
                    it->_cur->_pVec = nullptr;
                    //删除当前迭代器节点,继续判断后面的迭代器节点是否失效
                    pre->_next = it -> _next;
                    delete it;
                    it = pre->_next;
                }
                else
                {
                    pre = it;
                    it = it->_next;
                }
            }
        }


        //需要给容器提供begin和end方法
        iterator begin() 
        { 
            return iterator(this,_first);
        }
        iterator end() 
        {
            return iterator(this,_last);
        }

        //自己定义vector容器的insert方法的实现
        iterator insert(iterator it, const T &val)
        {
            /*
            1.不考虑扩容  verify(it._first - 1,_last);
            2.不考虑it._ptr - 1指针的合法性
            */
           verify(it._ptr - 1,_last);
           T *p = _last;
           while(p > it._ptr)
           {
               _allocator.construct(p,*(p-1));
               _allocator.destroy(p-1);
               p--;
           }
           _allocator.construct(p,val);
           _last ++;
           return iterator(this,p);
        }

        //自己定义vector容器的erase方法的实现
        iterator erase(iterator it)
        {
            
           verify(it._ptr - 1,_last);
           T *p = it._ptr;
           while(p < _last -1)
           {
               _allocator.destroy(p);
               _allocator.construct(p,*(p+1));
               p++;
           }
           _allocator.destroy(p);
           _last --;
           return iterator(this,it._ptr);
        }
    private:
        T *_first; // 指向数组起始的位置
        T *_last ; // 指向数组中有效元素的后继位置
        T *_end  ; // 指向数组空间的后继位置
        Alloc _allocator; //定义容器的空间配置器对象

        //容器迭代器失效增加代码
        struct Iterator_Base
        {
            Iterator_Base(Iterator *c = nullptr, Iterator_Base *n = nullptr)
                :_cur(c), _next(n){}
            iterator *_cur;
            Iterator_Base *_next;
        };
        Iterator_Base _head;


        void expand()
        {
            int size = _end - _first;
            // T *temp = new T[size * 2];
            T *temp = _allocator.allocate(2*size);
            for (int i = 0; i < size; i++)
            {
                // temp[i] = _first[i];
                _allocator.construct(temp+i,_first[i]);
            }
            // delete []_first;
            for(T *p = _first; p != _last; ++p)
            {
                //把_first指针指向的数组的有效元素进行析构操作
                _allocator.destroy(p); 
            }
            //释放堆上的数组内存
            _allocator.deallocate(_first); 

            _first = temp;
            _last = _first + size;
            _end  = _first + size * 2;

        }

};

new 和 delete 重载

重载new delete 的应用: 比如检测内存泄漏,在重载函数中增加一个内存映射,释放内存的时候删除这个映射的内存就行。然后程序结束之后打印就可以看到有没有释放完全了。

1.malloc 和 new 的区别?

        a: malloc 按字节开辟内存的;new开辟内存时需要指定类型,new int[]

                所以malloc开辟内存返回的都是void* 而new:operator new -> int *

        b:malloc 只负责开辟空间, new不仅仅有malloc的功能,可以进行数组的初始化 new int(20); new int[20]();

        c:malloc开辟内存失败返回nullptr指针,new抛出的是bad_alloc 类型的异常;

2.free和delete的区别?

        delete (int*)p; 先调用析构函数;再析构free(p);

3.new 和 delete能混用吗?

        对于普通的编译器内置类型new/delete[] new[]/delete,是没有任何问题的

        不能:

                Test *p = new Test[]; delete p;

                Test *p = new Test(); delete p[];

4. C++为什么区分单个元素和数组的内存分配和释放呢?

        自定义的类类型,有析构函数,为了调用正确的析构函数,那开辟对象数组的时候会多开辟4个字节,记录对象的个数

        a.如果 new Test[] 用delete释放的话,就会从那多出来的4个字节地址开始释放就会报错

        b.用delete[]就会去取4个字节的内存对象的个数,然后就能拿到每个正确的对象地址

//先调用operator new 开辟内存空间、然后调用对象的构造函数(初始化)
void* operator new(size_t size)
{
    void *p = malloc(size);
    if(p == nullptr) throw bad_alloc();
    return p;
}

//delete p; 调用p指向对象的析构函数,再调用operator delete 释放内存空间
void operator delete(void *ptr)
{
    free(ptr);
}

//数组new
void* operator new[](size_t size)
{
    void *p = malloc(size);
    if(p == nullptr) throw bad_alloc();
    return p;
}

//数组delete
void operator delete[](void *ptr)
{
    free(ptr);
}

class Test
{
    public:
        Test(int data = 10) : ptr(new int(data))
        {
            cout << "Test()" <<endl;
        }
        ~Test() 
        {
            delete ptr;
            cout << "~Test()" << endl;
        }
    private:
        int *ptr;
};

new 和 delete 重载实现对象池应用

#include <iostream>
#include <cstring>
using namespace std; 

template<typename T>
class Queue
{
    public:
        Queue()
        {
            _front = _rear = new QueueItem();
        }
        ~Queue()
        {
            QueueItem *cur = _front;
            while(cur != nullptr)
            {
                _front = _front->_next;
                delete cur;
                cur = _front;
            }
        }
        void push(const T &val)
        {
            QueueItem *item = new QueueItem(val);
            _rear->_next = item;
            _rear = item;
        }

        void pop()
        {
            if(empty())
                return ;
            QueueItem *first = _front->_next;
            _front->_next = first->_next;
            if(_front->_next == nullptr)
            {
                _rear = _front;
            }
            delete first;
        }
        T front() const
        {
            return _front->_next->_data;
        }

        bool empty()const 
        {
            return _front == _rear;
        }
    private:
        struct QueueItem
        {
            QueueItem(T data = T()):_data(data),_next(nullptr) {}
            //提升效率#1 增加给QueueItem提供自定义内存管理
            void* operator new (size_t size)
            {
                if(_itemPool ==  nullptr)
                {
                    _itemPool = (QueueItem *)new char[POOL_ITEM_SIZE * sizeof(QueueItem)];
                    QueueItem *p = _itemPool;
                    for(;p < _itemPool + POOL_ITEM_SIZE -1; ++p)
                    {
                        p->_next = p + 1;
                    }
                    p->_next = nullptr;
                }
                QueueItem *p = _itemPool;
                _itemPool = _itemPool->_next;
                return p;
            }
            void operator delete(void *ptr)
            {
                QueueItem *p = (QueueItem*)ptr;
                p->_next = _itemPool;
                _itemPool = p;
            }

            T _data;
            QueueItem *_next;
            static QueueItem *_itemPool; //指向池内存的首地址
            static const int POOL_ITEM_SIZE = 10000;
        };
        QueueItem *_front; //指向队头元素
        QueueItem *_rear;  //指向队尾

};

template<typename T>
typename Queue<T>::QueueItem *Queue<T>::QueueItem::_itemPool = nullptr;

int main()
{

    Queue<int> que;
    for(int i = 0; i < 1000000; ++i)
    {
        que.push(i); //申请内存
        que.pop();  //释放内存
        //以上两操作很频繁,性能不好。现在给QueueItem提供自定义内存管理
    }
    cout << que.empty() << endl;
    
    return 0;
}



这篇关于C++对象运算符重载,容器迭代器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程