自建一个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)。
原文地址:https://www.cnblogs.com/sunstars/p/3996161.html