zoukankan      html  css  js  c++  java
  • 自建一个String类实现深拷贝<<0925

    
    #include <iostream>
    #include <string.h>
    #include <vector>
    using namespace std;//在class里面存在指针的时候,要使用深拷贝,此时注意三法则原则
    
    class String
    {
        public:
            String();
            String(const char* s);
            String(const String &s);
            String &operator=(const String &s);
            String &operator=(const char* s);
            void print();
            ~String();
        private:
            char *str_;
    };
    
    String::String()
        :str_(new char(0))//mark;
    {}
    
    String::String(const char*s)
        :str_(new char[strlen(s) + 1])
    {
        strcpy(str_,s);
    }
    
    String::String(const String &s)
        :str_(new char[strlen(s.str_) + 1])//分配空间
    {
        strcpy(str_,s.str_);
    }
    
    String &String::operator=(const String &s)
    {
        if (str_ != s.str_)//避免给自身赋值,造成delete掉自己的数据
        {
            delete [] str_;
            str_ = new char[strlen(s.str_) + 1];
            strcpy(str_,s.str_);
        }
        return *this;//处理方式,不要漏掉*
    }
    
    String &String::operator=(const char* s)
    {
        if (str_ != s)//避免给自身赋值,造成delete掉自己的数据
        {
            delete [] str_;
            str_ = new char[strlen(s) + 1];
            strcpy(str_,s);
        }
        return *this;
    }
    
    String::~String()
    {
        delete [] str_;
    }
    
    void String::print()
    {
        cout << str_ << endl;
    }
    
    int main(int argc, const char *argv[])
    {
        String s1("hello world!");
        String s2,s3;
        s2 = s3 = s1;
        String s4(s1);
        s1.print();
        s2.print();
        s3.print();
        s4.print();
        s2 = s2;
        s2.print();
        return 0;
    }
    

    mark

    1. 赋值操作符,需要先释放掉以前持有的资源。同时必须处理自身赋值的问题。
    2. 复制构造函数、赋值运算符以及析构函数,称为三法则,一旦提供了其中一个,务必提供其余两个。以String为例:
      a) 涉及到深拷贝、浅拷贝问题,所以需要提供拷贝构造函数
      b) 然后,为了保持一致,赋值运算符也应该实现深拷贝
      c) 既然实现深拷贝,那么必定申请了资源(例如内存),所以必然需要析构函数来手工释放。
    3. 一个空类,编译器提供默认无参数构造函数、拷贝构造函数、赋值运算符以及析构函数,一共四个函数。
    4. 禁止一个类复制和赋值的方法:
      a) 把copy构造函数和赋值运算符设为private
      b) 只声明,不实现。
    5. 复制和赋值必须保证在程序的语义上具有一致性。
    6. 禁止类的复制和赋值:
      #define DISALLOW_COPY_AND_ASSIGN(TypeName) TypeName(const TypeName&);
      void operator=(const TypeName&)
    7. 如果一个类,不需要复制和赋值,那就禁用这种能力,这可以帮助避免大量潜在的bug。
    8. 如果一个类,实现了像value一样的复制和赋值能力(意味着复制和赋值后,两个对象没有任何关联,或者逻辑上看起来无任何关联),那么就称这个类的对象为值语义(value semantics)。如果类不能复制,或者复制后对象之间的资源归属纠缠不清,那么称为对象语义(object semantics),或者引用语义(reference semantics)。
  • 相关阅读:
    react-native window下创建Hello(解决创建一路的坑)
    vue2.0 监听滚动 锚点定位
    vue-awesome-swiper 轮播图使用
    vue和react区别
    vuex 管理状态
    vue 解决axios 跨域问题
    判断一个对象是否为空? js
    微信小程序中的自定义组件(components)
    深入理解ES6箭头函数中的this
    vue中组件的data为什么是一个函数
  • 原文地址:https://www.cnblogs.com/sunstars/p/3996161.html
Copyright © 2011-2022 走看看