• 第十三章 复制控制


    code:

    /*
    
    
    第13章 复制控制
    13.1 复制构造函数
    13.2 赋值操作符
    13.3 析构函数
    13.4 消息处理示例
    13.5 管理指针成员
    小结
    
    
    
    
    
    第13章 复制控制 405
    13.1 复制构造函数 406
    13.1.1 合成的复制构造函数 409
    13.1.2 定义自己的复制构造函数 409
    13.1.3 禁止复制 410
    13.2 赋值操作符 411
    13.3 析构函数 412
    13.4 消息处理示例 415
    13.5 管理指针成员 419
    13.5.1 定义智能指针类 421
    13.5.2 定义值型类 425
    小结 427
    术语 427
    
    
    */
    
    
    
    
    //13.1 复制构造函数 -------------------------------------------------------------------------------------------------
    
    
    
    // 如果我们没有定义复制构造函数,编译器就会为我们合成一个。合成的效果如同:
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Sales_item
    {
      public:
        Sales_item::Sales_item(const Sales_item &orig):
          isbn(orig.isbn),             // uses string copy constructor
          units_sold(orig.units_sold), // copies orig.units_sold
        revenue(orig.revenue)          // copy orig.revenue
        {}                             // empty body
      // other members and constructors as before
      private:
        std::string isbn;
        int units_sold;
        double revenue;
    };
    
    int main()
    {
      return 0;
    }
    
    
    
    //13.2 赋值操作符 -------------------------------------------------------------------------------------------------
    
    /*
    重载操作符是一些函数,其名字为 operator 后跟着所定义的操作符的符号。因此,通过定义名为 operator= 的函数,
    我们可以对赋值进行定义。像任何其他函数一样,操作符函数有一个返回值和一个形参表。形参表必须具有与该操作符数目
    相同的形参(如果操作符是一个类成员,则包括隐式 this 形参)。赋值是二元运算,所以该操作符函数有两个形参:
    第一个形参对应着左操作数,第二个形参对应右操作数。
    大多数操作符可以定义为成员函数或非成员函数。当操作符为成员函数时,它的第一个操作数隐式绑定到 this 指针。
    有些操作符(包括赋值操作符)必须是定义自己的类的成员。因为赋值必须是类的成员,所以 this 绑定到指向左操作数的指针。
    因此,赋值操作符接受单个形参,且该形参是同一类类型的对象。右操作数一般作为 const 引用传递。
    */
    
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Sales_item
    {
      public:
        // other members as before
        // equivalent to the synthesized assignment operator
        Sales_item &operator = (const Sales_item &); // 声明
    };
    
    int main()
    {
      return 0;
    }
    
    
    // =
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Sales_item
    {
      public:
        // other members as before
        // equivalent to the synthesized assignment operator
        Sales_item &operator = (const Sales_item &); // 声明
      private:
        std::string isbn;
        int units_sold;
        double revenue;
    };
    
    // equivalent to the synthesized assignment operator
    Sales_item &Sales_item::operator = (const Sales_item &rhs) // 定义
    {
      isbn = rhs.isbn; // calls string::operator=
      units_sold = rhs.units_sold; // uses built-in int assignment
      revenue = rhs.revenue; // uses built-in double assignment
      return  *this;
    }
    
    int main()
    {
      return 0;
    }
    
    
    
    //13.3 析构函数 -------------------------------------------------------------------------------------------------
    
    /*
    如果类需要析构函数,则它也需要赋值操作符和复制构造函数,这是一个有用的经验法则。这个规则常称为三法则,
    指的是如果需要析构函数,则需要所有这三个复制控制成员。
    析构函数与复制构造函数或赋值操作符之间的一个重要区别是,即使我们编写了自己的析构函数,合成析构函数仍然运行。
    */
    
    
    //13.4 消息处理示例 -------------------------------------------------------------------------------------------------
    
    
    // in book,本身就缺少 save...
    
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Message
    {
      public:
        // folders is initialized to the empty set automatically
        Message(const std::string &str = ""): contents(str){}
        // copy control: we must manage pointers to this Message
        // from the Folders pointed to by folders
        Message(const Message &);
        Message &operator = (const Message &);
        ~Message();
        // add/remove this Message from specified Folder's set of messages
        void save(Folder &);
        void remove(Folder &);
      private:
        std::string contents; // actual message text
        std::set < Folder * > folders; // Folders that have this Message
        // Utility functions used by copy constructor, assignment, and destructor:
        // Add this Message to the Folders that point to the parameter
        void put_Msg_in_Folders(const std::set < Folder * >  &);
        // remove this Message from every Folder in folders
        void remove_Msg_from_Folders();
    };
    
    Message::Message(const Message &m): contents(m.contents), folders(m.folders)
    {
      // add this Message to each Folder that points to m
      put_Msg_in_Folders(folders);
    }
    
    // add this Message to Folders that point to rhs
    void Message::put_Msg_in_Folders(const set < Folder * >  &rhs)
    {
      for(std::set < Folder * > ::const_iterator beg = rhs.begin(); beg != rhs.end()
        ; ++beg)
        (*beg)->addMsg(this);
      // *beg points to a Folder
    }
    
    Message &Message::operator = (const Message &rhs)
    {
      if(&rhs != this)
      {
        remove_Msg_from_Folders(); // update existing Folders
        contents = rhs.contents; // copy contents from rhs
        folders = rhs.folders; // copy Folder pointers from rhs
        // add this Message to each Folder in rhs
        put_Msg_in_Folders(rhs.folders);
      }
      return  *this;
    }
    
    // remove this Message from corresponding Folders
    void Message::remove_Msg_from_Folders()
    {
      // remove this message from corresponding folders
      for(std::set < Folder * > ::const_iterator beg = folders.begin(); beg !=
        folders.end(); ++beg)
        (*beg)->remMsg(this);
      // *beg points to a Folder
    }
    
    Message::~Message()
    {
      remove_Msg_from_Folders();
    }
    
    int main()
    {
      return 0;
    }
    
    
    // 还要添加Folder类等,未完成
    #include <iostream>
    #include <string>
    #include <set>
    using namespace std;
    
    class Message
    {
      public:
        // contents初始化为空串
        Message(const string &str = ""): contents(str){}
        Message(const Message &); // 复制构造函数
        Message &operator = (const Message &); // 重载赋值运算符
        ~Message(); // 析构函数
        void save(Folder &); // 添加信息
        void remove(Folder &); // 移除信息
      private:
        string contents; // 信息文本内容
        set < Folder * > folders; // folders 是 Folder的指针集合
        void put_Msg_in_Folders(const std::set < Folder * >  &); // 将信息指针,加入folders集合
        void remove_Msg_from_Folders(); // 将信息指针,从folders集合中移除
    };
    
    // 复制构造函数
    Message::Message(const Message &m) : contents(m.contents), folders(m.folders)
    {
      // add this Message to each Folder that points to m
      put_Msg_in_Folders(folders);
    }
    
    // add this Message to Folders that point to rhs
    void Message::put_Msg_in_Folders(const set < Folder * >  &rhs)
    {
      for(set < Folder * > ::const_iterator beg = rhs.begin();
        beg != rhs.end(); ++beg)
        (*beg)->addMsg(this); // ??
      // *beg points to a Folder
    }
    
    // 重载赋值运算符
    Message &Message::operator = (const Message &rhs)
    {
      if(&rhs != this)
      {
        remove_Msg_from_Folders(); // update existing Folders
        contents = rhs.contents;   // copy contents from rhs
        folders = rhs.folders;     // copy Folder pointers from rhs
        // add this Message to each Folder in rhs
        put_Msg_in_Folders(rhs.folders);
      }
      return  *this;
    }
    
    // remove this Message from corresponding Folders
    void Message::remove_Msg_from_Folders()
    {
      // remove this message from corresponding folders
      for(std::set < Folder * > ::const_iterator beg = folders.begin();
        beg !=folders.end(); ++beg)
        (*beg)->remMsg(this);
      // *beg points to a Folder
    }
    
    Message::~Message()
    {
      remove_Msg_from_Folders();
    }
    
    int main()
    {
      return 0;
    }
    
    
    //13.5 管理指针成员 -------------------------------------------------------------------------------------------------
    
    
    // my test
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main()
    {
      int i(3);
      int *pa, *pb;
      pa=&i; pb=&i;
      *pa = 0; // 任一指针,都可以改变原来的指向内容
      cout << *pb << endl;
      
      return 0;
    }
    
    
    
    // in book
    #include <iostream>
    #include <string>
    using namespace std;
    // class that has a pointer member that behaves like a plain pointer
    class HasPtr
    {
      public:
        // copy of the values we're given
        HasPtr(int *p, int i): ptr(p), val(i){}
        
        // const members to return the value of the indicated data member
        int *get_ptr()const { return ptr; } 
        int get_int()const  { return val; }
        
        // non const members to change the indicated data member
        void set_ptr(int *p) { ptr = p; }
        void set_int(int i)  { val = i; }
        
        // return or change the value pointed to, so ok for const objects
        int get_ptr_val()const { return  *ptr; }
        void set_ptr_val(int val)const { *ptr = val; }
        
      private:
        int *ptr;
        int val;
    };
    
    int main()
    {
      int i(3);
      HasPtr cptr(&i,i);
      cout << cptr.get_ptr() << endl; // 地址
      cout << cptr.get_int() << endl; //
      cout << cptr.get_ptr_val() << endl; //
      cptr.set_ptr_val(8);
      cout << cptr.get_ptr_val() << endl; ////
      int j(10);
      cptr.set_ptr(&j);
      cout << cptr.get_ptr_val() << endl;
      
      return 0;
    }
    
    
    // 指针复制
    #include <iostream>
    #include <string>
    using namespace std;
    // class that has a pointer member that behaves like a plain pointer
    class HasPtr
    {
      public:
        // copy of the values we're given
        HasPtr(int *p, int i): ptr(p), val(i){}
        
        // const members to return the value of the indicated data member
        int *get_ptr()const { return ptr; } 
        int get_int()const  { return val; }
        
        // non const members to change the indicated data member
        void set_ptr(int *p) { ptr = p; }
        void set_int(int i)  { val = i; }
        
        // return or change the value pointed to, so ok for const objects
        int get_ptr_val()const { return  *ptr; }
        void set_ptr_val(int val)const { *ptr = val; }
        
      private:
        int *ptr;
        int val;
    };
    
    int main()
    {
      int obj = 0;
      HasPtr ptr1(&obj, 42); // int* member points to obj, val is 42
      cout << ptr1.get_ptr() << endl; // ptr1.ptr
      HasPtr ptr2(ptr1);     // int* member points to obj, val is 42
      cout << ptr2.get_ptr() << endl; // ptr2.ptr
      // 我们会发现,两个地址一模一样,复制的嘛
      
      return 0;
    }
    
    
    // in book
    #include <iostream>
    #include <string>
    using namespace std;
    
    // class that has a pointer member that behaves like a plain pointer
    class HasPtr
    {
      public:
        // copy of the values we're given
        HasPtr(int *p, int i): ptr(p), val(i){}
        
        // const members to return the value of the indicated data member
        int *get_ptr()const { return ptr; } 
        int get_int()const  { return val; }
        
        // non const members to change the indicated data member
        void set_ptr(int *p) { ptr = p; }
        void set_int(int i)  { val = i; }
        
        // return or change the value pointed to, so ok for const objects
        int get_ptr_val()const { return  *ptr; }
        void set_ptr_val(int val)const { *ptr = val; }
        
      private:
        int *ptr;
        int val;
    };
    
    int main()
    {
      int obj = 0;
      HasPtr ptr1(&obj, 42); // int* member points to obj, val is 42
      HasPtr ptr2(ptr1); // int* member points to obj, val is 42
      
      ptr1.set_int(0); // changes val member only in ptr1
      cout << ptr2.get_int() << endl; // returns 42
      cout << ptr1.get_int() << endl; // returns 0
      // 说明整数副本是独立的
      
      ptr1.set_ptr_val(42); // sets object to which both ptr1 and ptr2 point
      cout << ptr1.get_ptr_val() << endl; // returns 42
      cout << ptr2.get_ptr_val() << endl; // returns 42
      // 因为两指针值得是一样的,所以两val都一样了
      
      int *ip = new int(42); // dynamically allocated int initialized to 42
      HasPtr ptr(ip, 10); // Has Ptr points to same object as ip does
      delete ip; // object pointed to by ip is freed
      ptr.set_ptr_val(0); // disaster: The object to which Has Ptr points was freed!
      
      return 0;
    }
    
    
    // 13.5.1. 定义智能指针类
    
    #include <iostream>
    #include <string>
    using namespace std;
    
    // private class for use by HasPtr only
    class U_Ptr {
        friend class HasPtr;
        int *ip;
        size_t use;
        U_Ptr(int *p): ip(p), use(1) { }
        ~U_Ptr() { delete ip; }
    };
    
    /*smart pointer class: takes ownership of the dynamically allocated
    *   object to which it is bound
    * User code must dynamically allocate an object to initialize a HasPtr
    * and must not delete that object; the HasPtr class will delete it
    */
    class HasPtr {
      public:
        // HasPtr owns the pointer; p must have been dynamically allocated
        HasPtr(int *p, int i): ptr(new U_Ptr(p)), val(i) { }
    
        // copy members and increment the use count
        HasPtr(const HasPtr &orig):
          ptr(orig.ptr), val(orig.val) { ++ptr->use; } // add use
        HasPtr& operator=(const HasPtr&);
    
        // if use count goes to zero, delete the U_Ptr object
        ~HasPtr() { if (--ptr->use == 0) delete ptr; }
    
    
        // copy control and constructors as before
        // accessors must change to fetch value from U_Ptr object
        int *get_ptr() const { return ptr->ip; }
        int get_int() const { return val; }
    
        // change the appropriate data member
        void set_ptr(int *p) { ptr->ip = p; }
        void set_int(int i) { val = i; }
    
        // return or change the value pointed to, so ok for const objects
        // Note: *ptr->ip is equivalent to *(ptr->ip)
        int get_ptr_val() const { return *ptr->ip; }
        void set_ptr_val(int i) { *ptr->ip = i; }
    
      private:
        U_Ptr *ptr;  // points to use-counted U_Ptr class
        int val;
    };
    
    HasPtr &HasPtr::operator = (const HasPtr &rhs)
    {
      ++rhs.ptr->use; // increment use count on rhs first
      if(--ptr->use == 0)
        delete ptr;
      // if use count goes to 0 on this object, delete it
      ptr = rhs.ptr; // copy the U_Ptr object
      val = rhs.val; // copy the int member
      return  *this;
    }
    
    
    int main()
    {
     
      return 0;
    }
    
    
    
    // 13.5.2. 定义值型类
    
    // in book
    #include <iostream>
    #include <string>
    using namespace std;
    
    /*
    * Valuelike behavior even though HasPtr has a pointer member:
    * Each time we copy a HasPtr object, we make a new copy of the
    * underlying int object to which ptr points.
    */
    class HasPtr {
      public:
        // no point to passing a pointer if we're going to copy it anyway
        // store pointer to a copy of the object we're given
        HasPtr(const int &p, int i): ptr(new int(p)), val(i) {}
    
        // copy members and increment the use count
        HasPtr(const HasPtr &orig):
          ptr(new int (*orig.ptr)), val(orig.val) {}
    
        HasPtr& operator=(const HasPtr&);
        ~HasPtr() { delete ptr; }
        // accessors must change to fetch value from Ptr object
        int get_ptr_val() const { return *ptr; }
        int get_int() const { return val; }
    
        // change the appropriate data member
        void set_ptr(int *p) { ptr = p; }
        void set_int(int i) { val = i; }
    
        // return or change the value pointed to, so ok for const objects
        int *get_ptr() const { return ptr; }
        void set_ptr_val(int p) const { *ptr = p; }
      private:
        int *ptr;  // points to an int
        int val;
    };
    
    HasPtr& HasPtr::operator=(const HasPtr &rhs)
    {
      // Note: Every HasPtr is guaranteed to point at an actual int;
      // We know that ptr cannot be a zero pointer
      *ptr = *rhs.ptr;       // copy the value pointed to
      val = rhs.val;         // copy the int
      return *this;
    }
    
    int main()
    {
      
      return 0;
    }
    
    
    // my test
    #include <iostream>
    #include <string>
    using namespace std;
    
    /*
    * Valuelike behavior even though HasPtr has a pointer member:
    * Each time we copy a HasPtr object, we make a new copy of the
    * underlying int object to which ptr points.
    */
    class HasPtr {
      public:
        HasPtr():ptr(new int(0)),val(0){} // 如果木有参数
    
        // no point to passing a pointer if we're going to copy it anyway
        // store pointer to a copy of the object we're given
        HasPtr(const int &p, int i): ptr(new int(p)), val(i) {}
        // new int(p):在堆中申请一个内存,存放整数p。返回申请到的内存指针
    
        // copy members and increment the use count
        HasPtr(const HasPtr &orig):
          ptr(new int (*orig.ptr)), val(orig.val) {}
    
        HasPtr& operator=(const HasPtr&);
        ~HasPtr() { delete ptr; }
        // accessors must change to fetch value from Ptr object
        int get_ptr_val() const { return *ptr; }
        int get_int() const { return val; }
    
        // change the appropriate data member
        void set_ptr(int *p) { ptr = p; }
        void set_int(int i) { val = i; }
    
        // return or change the value pointed to, so ok for const objects
        int *get_ptr() const { return ptr; }
        void set_ptr_val(int p) const { *ptr = p; }
      private:
        int *ptr;  // points to an int
        int val;
    };
    
    HasPtr& HasPtr::operator=(const HasPtr &rhs)
    {
      // Note: Every HasPtr is guaranteed to point at an actual int;
      // We know that ptr cannot be a zero pointer
      *ptr = *rhs.ptr;       // copy the value pointed to
      val = rhs.val;         // copy the int
      return *this;
    }
    
    
    int main()
    {
      int *pi = new int(1024);  // object to which pi points is 1024
      cout << *pi << endl << endl;
      delete pi;
      
      HasPtr ptra(2,3);
      cout << ptra.get_ptr_val() << endl;
      cout << ptra.get_int() << endl << endl;
      
      HasPtr ptrb;
      ptrb=ptra;
      cout << ptrb.get_ptr_val() << endl;
      cout << ptrb.get_int() << endl << endl;  
      
      int n(5);
      ptrb.set_ptr(&n);
      ptrb.set_int(8);
      cout << ptrb.get_ptr_val() << endl;
      cout << ptrb.get_int() << endl;   
      
      return 0;
    }

    TOP

  • 相关阅读:
    LOJ2323. 「清华集训 2017」小 Y 和地铁 【搜索】【思维】【好】
    BZOJ2687 交与并/BZOJ2369 区间【决策单调性优化DP】【分治】
    BZOJ1563 NOI2009 诗人小G【决策单调性优化DP】
    LOJ6039. 「雅礼集训 2017 Day5」珠宝【决策单调性优化DP】【分治】【思维好题】
    BZOJ4709 Jsoi2011 柠檬【决策单调性+单调栈】
    BZOJ2216 Poi2011 Lightning Conductor 【决策单调性优化DP】
    BZOJ3675 Apio2014 序列分割 【斜率优化】
    BZOJ4566 Haoi2016 找相同字符【广义后缀自动机】
    51nod 1600 Simple KMP【后缀自动机+LCT】【思维好题】*
    linux usermod
  • 原文地址:https://www.cnblogs.com/xin-le/p/4087978.html
Copyright © 2020-2023  润新知