zoukankan      html  css  js  c++  java
  • 19.C++-(=)赋值操作符、初步编写智能指针

    (=)赋值操作符

    • 编译器为每个类默认重载了(=)赋值操作符
    • 默认的(=)赋值操作符仅完成浅拷贝
    • 默认的赋值操作符和默认的拷贝构造函数有相同的存在意义

    (=)赋值操作符注意事项

    首先要判断两个操作数是否相等

    返回值一定是 return *this; 返回类型是Type&型,避免连续使用=后,出现bug

    比如:

    class Test{
           int *p;
    
           Test(int i)
           {
                  p=new int(i);
           }
    Test
    & operator = (const Test& obj) { if(this!=&obj) { delete p; p=new int(*obj.p); } return *this; } };

    注意:指针对象之间赋值是不会调用(=)复制操作符的

    编译器默认提供的类函数

    包括了:构造函数,析构函数,拷贝构造函数, (=)赋值操作符

    智能指针

    智能指针的由来

    在以前C程序里,使用malloc()等函数动态申请堆空间时,若不再需要的内存没有被及时释放,则会出现内存泄漏,若内存泄漏太多,则会直接导致设备停止运行,特别是嵌入式设备,可能有些设备一上电就要运行好几个月.

    在C++里,为了减少内存泄漏,所以便引出了智能指针

    介绍

    • 智能指针实际上是将指针封装在一个类里,通过对象来管理指针.
    • 构造函数时,通过对象将指针传递进来,指针可以是缺省值.
    • 然后构造-> ” “ * ” “ = 操作符重载,让这个对象拥有指针的特性.
    • 最后通过析构函数,来释放类里的指针.

    注意

    • 智能指针只能指向堆空间中的对象或者变量
    • 并且一片空间最多只能由一个智能指针标识(因为多个指向地址相同的智能指针调用析构函数时,会出现bug)
    • ->和*都是一元操作符,也就是说不能带参数

    比如ptr->value的->:

    当ptr的类型是普通指针类型时,等价于:(*ptr).mem

    当ptr的类型是时,等价于:(ptr.operator->())->value    等价于: ( *(ptr.operator->()) ).value

    所以->操作符函数的返回类型是type*,返回值是一个指针变量本身(不带*)

    具体参考: https://segmentfault.com/q/1010000004620896

    接下来个示例,指向一个int型的智能指针

    #include <iostream>
     
    using namespace std;
    
    class Point{
    int *p; public: Point(int *p=NULL) { this->p = p; } int* operator -> () { return p; } int& operator *() { return *p; } ~Point() { cout<<"~Point()"<<endl; delete p; } }; int main() { for(int i=0;i<5;i++) { Point p=new int(i); cout <<*p<<endl; } return 0; }

    运行打印:

    0
    ~Point()
    1
    ~Point()
    2
    ~Point()
    3
    ~Point()
    4
    ~Point()

    从结果可以看到, Point p每被从新定义之前,便会自动调用析构函数来释放之前用过的内存,

    这样便避免了野指针的出现

    接下来,我们继续完善上面代码,使它能够被赋值.

    #include <iostream>
    using namespace std; class Point{ int *p; public: Point(int *p=NULL) { this->p = p; } bool isNULL() { return (p==NULL); } int* operator -> () { return p; }  
    int& operator *() { return *p; } Point& operator = (const Point& t) { cout<<"operator =()"<<endl; if(this!=&t) { delete p; p = t.p; const_cast<Point&>(t).p=NULL; //去掉const类型参数 } return *this; } ~Point() { cout<<"~Point()"<<endl; delete p; } }; int main() { Point p=new int(2); Point p2; p2= p; //等价于 p2.operator= (p); cout <<"p=NULL:"<<p.isNULL()<<endl; *p2+=3; //等价于 *(p2.operator *())=*(p2.operator *())+3;              //p2.operator *()返回一个int指针,并不会调用Point类的=操作符 cout <<"*p2="<<*p2 <<endl; return 0; }

    运行打印:

    operator =()       
    
    p=NULL:1              // Point  p的成员已被释放
    
    *p2=5
    
    ~Point()
    ~Point()

    但是,还有个缺点,就是这个智能指针仅仅只能指向int类型,没办法指向其它类型. 

    接下来继续修改,通过类模板来使这个智能指针能指向多种类型

    #include <iostream>
    
    using namespace std;
    
    template <typename T>
    class Point
    {
        T *p;
    public:
        Point(T *p)
        {
            this->p = p; 
        }
        bool isNULL()
        {
            return (p==NULL);
        }
        
        T* operator -> ()
        {
            return p; 
        } 
        
        T& operator *()
        {
            return *p; 
        } 
        
        Point& operator = (const Point& t)
        {
                  cout<<"operator =()"<<endl;
    
                  if(this!=&t)
                  {
                         delete p;
                         p = t.p;
                         const_cast<Point&>(t).p=NULL;   //去掉const类型参数
                  }         
                  return *this;
         }
      
        ~Point()
        {
            delete p;    
        } 
    
    };
     
    int main()
    {       
           Point<int> p1=new int(2); 
           cout<<*p1<<endl; 
        
           Point<float> p2=new float(3.56);  
           cout<<*p2<<endl;
           
           return 0;
    }

    运行打印:

    2
    3.56
    ~Point()
    ~Point()
  • 相关阅读:
    Linux下sed,awk,grep,cut,find学习笔记
    Python文件处理(1)
    KMP详解
    Java引用详解
    解决安卓中页脚被输入法顶起的问题
    解决swfupload上传控件文件名中文乱码问题 三种方法 flash及最新版本11.8.800.168
    null id in entry (don't flush the Session after an exception occurs)
    HQL中的Like查询需要注意的地方
    spring mvc controller间跳转 重定向 传参
    node to traverse cannot be null!
  • 原文地址:https://www.cnblogs.com/lifexy/p/8658605.html
Copyright © 2011-2022 走看看