运算符重载及STL总结

一:运算符重载

1、基本概念:运算符重载使得用户自定义的数据以一种更简洁的方式工作。

(1)声明与定义格式

类内声明:

class X

{

返回类型 operator运算符(形参表);

}

类外定义:

返回类型X::operator运算符(形参表)

{函数体}

(2)双目运算符重载为成员函数,形参表中只有一个参数,作为运算符的右操作数,当前对象作为左操作数,通过this指针隐式传递给函数。

用重载运算符加号来实现复数的加减,重载为成员函数,只有一个参数,代表右操作数,左操作数是对象本身。

(3)单目运算符重载为成员函数,参数表中没有参数,此时当前对象作为运算符的一个操作数。

无形参时代表前自增,返回自加后对象,有形参代表后自增,返回自加之前的对象。

2、用友元函数重载

(1)常用于运算符左右操作数类型不同的情形

在第一个函数需要隐式转换的情形下,使用友元函数重载

友元函数没有this指针时,所需操作数都需在参数表显示声明。

用友元函数重载,做复数加减运算,左右操作数都需显示声明。

(2)与成员函数重载的区别

比成员函数少一个参数

操作数类型不同,必须友元重载

3、常用重载函数应用:

(1)赋值运算符重载用于对象数据的复制

opertaor=必须重载为友元函数

重载函数原型

类名&类名::operator=类名

重载=与复制构造函数类似作用,但要注意复制构造函数是构造对象时调用,重载赋值运算符是对象构造完成后调用。

(2)重载运算符[]和()

是二元运算符,只能用成员函数重载。

[]下标运算符,访问数据对象的元素

模拟动态数组,new int动态分配空间,重载下标运算符访问特定数据成员

()用于函数调用  格式:类型 类::operator()参数表

()可以看做调用函数,计算两个数的平方之和

(3)重载输入输出流(重点,常用)

重载输入输出流只能用友元

一般格式如下

重载输出流:

    ostream&operator<<(ostream& out,class_name&obj)

   { out<<obj.item1;

         out<<obj.item2;

        out<<obj.itemn;

         returnout;

    }

重载输入流:

    istream&operator>>(istream& in,class_name&obj)

    {   in>>obj.item1;

           in>>obj.item2;

           in>>obj.itemn;

           returnin;

 }

4、重载运算符中最常见的就是输入输出及小于大于号运算符,在一些时候重载运算符很方便,以一个程序为例:

#include<bits/stdc++.h>
using namespace std;
class complexs
{
private:
    int real;
    int imag;
public:
    complexs()
    {
        real=0;
        imag=0;
    }
    complexs(int a,intb):real(a),imag(b){}
    complexs operator+(complexs &c);//complexs
为返回类型,重载加号运算符;
    friendistream&operator>>(istream&,complexs&c);//
重载输入运算符
    friendostream&operator<<(ostream&,complexs&c);//
重载输出运算符

    friend booloperator<(complexs &c1,complexs &c2);//重载小于号运算符1

bool operator<(complex &c)//重载小于号运算符2;两种方法都行

{

return  (real<c.real&&imag<c.imag);

{

 

    voidshow(){cout<<real<<"\t"<<imag<<endl;};
};
bool operator<(complexs &c1,complexs&c2)
{
    return c1.real<c1.imag;
}
istream&operator>>(istream&input,complexs&c)
{
    cout<<"please inputreal and imag \t";
    input>>c.real>>c.imag;
    return input;
}
ostream&operator<<(ostream&output,complexs&c)
{
   if(c.imag>0)output<<"("<<c.real<<"+"<<c.imag<<"i)";//
而且,在重载过程中可以添加附加条件,便于程序调试;
   elseoutput<<"("<<c.real<<c.imag<<"i)";
    return output;
}
complexs complexs::operator+(complexs &c)
{
    returncomplexs(real+c.real,imag+c.imag);
}
int main()
{
    complexs c1(2,3),c2(2,3),c3;
    c3=c1+c2;
    c3.show();
    complexs c4,c5,c6;
    cin>>c4>>c5;
    c6=c4+c5;
    cout<<c6<<endl;
    if(c4<c5)cout<<"YES";
    else cout<<"NO";
    return 0;

}

//不能用友元函数重载的运算符有:=  ()  []

//重载=号和深复制复习

//不能用友元函数重载的运算符有:=  ()  []
#include<bits/stdc++.h>
using namespace std;
class name
{
    public:
    name(char *p);
    name(const name& );
    name &operator=(name&n);
    ~name();
    private:
    char *ppp;
    int size;
};
name::name(char *p)
{
    cout<<"construct"<<p<<endl;
    size=strlen(p);
    ppp=new char[size+1];
    if(ppp!=0)strcpy(ppp,p);
}
name::name(const name&ob)
{
   cout<<"copying"<<ob.ppp<<"into\n";
    size=ob.size;
    ppp=new char[size+1];
    if(ppp!=0)strcpy(ppp,ob.ppp);
}
name&name::operator=(name&n)
{
    delete[]ppp;
    size=n.size;
    ppp=new char[size+1];
    if(ppp!=0)strcpy(ppp,n.ppp);
    return *this;//return
的是此对象  return*this;
}
name::~name()
{
    cout<<"destruct"<<ppp<<endl;
    ppp[0]='\0';
    delete[]ppp;
    ppp=NULL;
    size=0;
}
int main()
{
    name obj("lalaa");
    name obj2=obj;
    name obj3("hahah");
    obj3=obj2=obj;

二:STL

1STL主要包括容器,目前最常用的就是vector;还有迭代器,相当于容器的一个副本,对元素进行遍历;还有算法,也就是对元素进行各种操作,有特殊的语句来执行。

(1)容器:

管理某类对象的集合,分为关联式容器(次序取决于插入时机位置)和序列式(取决于特定准则)

共同操作:

初始化、与大小相关的操作(size max_size() empty())、比较、赋值和交换、与迭代器相关的操作:(begin()、end()、rbegin()、rend())、元素操作(insert(pos,e)、erase(beg,end)、clear())

注:begin()返回第一个元素,end()返回最后一个元素之后

(2)迭代器::iterator

遍历STL容器内全部或部分元素

指出容器内特定元素位置

迭代器分类:

双向迭代器、随机存取迭代器

2、vector(重)

(1)基本概念:

vector模拟动态元素,元素可以是任意类型

必须包含头文件#include<vector>

vector支持随机存取

vector大小size(返回实际元素个数)和容量capacity(返回元素最大数量)

(2)、赋值:
c1=c2;
c.assign(n,e);将元素e的n个赋值拷贝给c
c.swap(c1);c1,c元素互换
swap(c,c1);同上

(3)操作
          vector<T>c : 产生空的vector

                vector<T>c1(c2) :产生同类型的c1,并将复制c2的所有元素

               vector<T>c(n) : 利用类型T的默认构造函数和拷贝构造函数生成一个大小为n的vector

                vector<T>c(n,e) : 产生一个大小为n的vector,每个元素都是e

                vector<T>c(beg,end) : 产生一个vector,以区间[beg,end]为元素初值

               vector<T>()  :  销毁所有元素并释放内存。

               c.empty()   判断容器是否为空

               c.capacity()   返回重新分配空间前可容纳的最大元素数量

                c.reserve(n)   扩大容量为n

                c1= c2  将c2的全部元素赋值给c1    

                 c.assign(beg,e[beg,end]nd)  将区间的元素赋值给c   

               at(idx) 返回索引idx所标识的元素的引用,进行越界检查

                operator[](idx) 返回索引idx所标识的元素的引用,不进行越界检查

                front() 返回第一个元素的引用,不检查元素是否存在

                back() 返回最后一个元素的引用,不检查元素是否存在

                c.push_back(e) 在尾部添加一个元素e的副本

              c.pop_back() 移除最后一个元素但不返回最后一个元素

vector<int> a;//定义一个元素类型为int,名称为a 的动态数组。  

    for (int i = 0; i < 5; ++i){  

        a.push_back(5 - i);//将5 4 3 2 1 依次放入a 里面  

   }  

    cout << "Size: " << a.size() << endl; //a当前的大小  

    a.pop_back(); //移除a 的最后一个元素  

    a[0] = 1;  

  

    cout << "Size: " << a.size() << endl;  

    for (int i = 0; i < (int)a.size(); ++i){  

        cout << a[i] << ", " << endl;  

    }  

    cout << endl;  

  

    sort(a.begin(), a.end());  

    cout << "Size: " << a.size() << endl;  

    for (int i = 0; i < (int)a.size(); ++i){  

        cout << a[i] << ", " << endl;  

    }  

    cout << endl;  

  

    a.clear();//清除a中所有元素  

    cout << "Size: " << a.size() << endl;  

 

3、map和multimap

(1)基本概念:

使用平衡二叉树管理,元素包括两部分(key,value),key是关键字,value是值,包含头文件#include<map>,map的key不同,multimap的key可以相同。

(2):

 元素包含两部分(key,value),key和value可以是任意类型

           必须包含的头文件#include <map>

            根据元素的key自动对元素排序,因此根据元素的key进行定位很快,但根据元素的value定位很慢

           不能直接改变元素的key,可以通过operator[]直接存取元素值
            map中不允许key相同的元素,multimap允许key相同的元素

(3)、multimap<string, int> mm1;//定义一个索引key是string,值valua是int的,名为mm1的  

multimap<string, int>::iterator mm1i, p1, p2;//定义p1,p2两个迭代器  

mm1.insert(make_pair("b", 3));//make_pair,生成  

mm1.insert(make_pair("a", 0));  

mm1.insert(make_pair("b", 5));  

mm1.insert(make_pair("c", 4));  

mm1.insert(make_pair("b", 2));  

cout << "Size: " << mm1.size() << endl;  

for(mm1i = mm1.begin(); mm1i != mm1.end(); mm1i++)  

{   cout << mm1i->first << ": " << mm1i->second << endl; }  

   cout << "COUNT: " << mm1.count("b") << endl;  

    cout << "Bound: " << endl;  

   p1 = mm1.lower_bound("b");  

    p2 = mm1.upper_bound("b");  

    for(mm1i = p1; mm1i != p2; mm1i++){  

    cout << mm1i->first << ": " << mm1i->second << endl;  

}  

 

4、set、multiset、pair

(1)set、multiset基本概念

使用平衡二叉树管理,包含头文件#include<set>,set是单纯的键的集合,set不允许键相同,multiset允许。

建立关键字字符串型的set,插入元素,建立迭代器,从头到尾遍历,输出元素值,再建立迭代器查找特定元素。

multiset类似,但可以有多个键相同的元素。

(3)pair生成key-value对

5、算法

count 计算一段范围内等于某个值的元素个数

count_if 计算一段范围内满足某个条件的元素个数

max_element 返回一段范围内最大元素的迭代器

for_each 遍历一段范围内的元素,调用函数

find 寻找特定元素第一次出现的位置,返回迭代器。

find_if 返回区间范围内满足制定条件的迭代器

binary_search折半查找,返回是否找到

lower_bound返回大于等于指定值的最小位置

upper_bound返回大于指定值的最小位置

sort快速排序,可以加一个条件形参,按条件排序

unique去重,返回迭代器,指向元素删除后区间最后一个元素后面

reverse 颠倒区间端点的顺序

三、心得

近期所学习的这些新知识的作用发大概就是可以简缩所写代码,把同样的功能用更精简的程序完成,明显的实现效率更高。经过这段时间的学习,不太好意思的说还是有点蒙的,并不是太清楚对新知识的使用。老师让我们为你把原来写的ATM用新学的ATL改一遍,应该就是为了锻炼我们的实用能力,就发现掌握的真的很不好。所以以后还需要努力,在多加的学习。先记住所学知识,再一步步地去运用,在不断地实践中真正地掌握它。充分利用网上的资源,弄懂自己不会的和不清楚的,顺便扩大自己的知识面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值