C++之Big Three:拷贝构造、拷贝赋值、析构函数探究

C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第1张图片
涉及到本文所讲知识点的博文:
C++之析构函数探究
C++之常引用和浅拷贝探究
C++之一个函数链的简单例子(分文件实现)
C++之Big Three:拷贝构造、拷贝赋值、析构函数探究
C++之操作符重载探究(五):赋值运算符重载和拷贝赋值函数(深拷贝)

Big Three:拷贝构造、拷贝赋值、析构函数(针对带着指针成员变量的类)。

例1:

C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第2张图片

例1分析:打字手累,直接贴好久好久以前研究本例知识点的笔记,有点啰嗦:

笔记第一页:
C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第3张图片
笔记第二页:
C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第4张图片
笔记第三页:

笔记第四页:
C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第5张图片
笔记第五页:
C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第6张图片
笔记第六页:
C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第7张图片
笔记第七页:(啥也没记)
C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第8张图片
笔记第八页:(啥也没记)
C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第9张图片
笔记第九页:
C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第10张图片
笔记第十页:(啥也没记)
C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第11张图片
附本例代码:

//小问学编程
#include 
#include 
using namespace std;

class String
{
public:
   String(const char* cstr=0);
   String(const String& str);
   String& operator=(const String& str);
   ~String();
   char* get_c_str() const { return m_data; }
private:
   char* m_data;
};

#include 

inline
String::String(const char* cstr)
{
   if (cstr) {
      m_data = new char[strlen(cstr)+1];
      strcpy(m_data, cstr);
   }
   else {
      m_data = new char[1];
      *m_data = '\0';
   }
}

inline
String::~String()
{
   delete[] m_data;
}

inline
String& String::operator=(const String& str)
{
   if (this == &str)
      return *this;

   delete[] m_data;
   m_data = new char[ strlen(str.m_data) + 1 ];
   strcpy(m_data, str.m_data);
   return *this;
}

inline
String::String(const String& str)
{
   m_data = new char[ strlen(str.m_data) + 1 ];
   strcpy(m_data, str.m_data);
}

ostream& operator<<(ostream& os, const String& str)
{
   os << str.get_c_str();
   return os;
}

int main()
{
  String s1("hello");
  String s2("world");

  String s3(s2);
  cout << s3 << endl;

  s3 = s1;
  cout << s3 << endl;
  cout << s2 << endl;
  cout << s1 << endl;
}

运行结果:

C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第12张图片

补充:拷贝构造函数

  拷贝构造函数:通过拷贝一个已经存在的对象来创建新的对象,也就是说,这个构造函数的参数就是另外一个对象。

  Vector(Vector& v);

   ♠ \spadesuit 用一个已存在的对象初始化另一个对象:

  classT object(another_object);

  classT object=another_object;
  (第二种情况编译器会调用拷贝构造函数而不是赋值操作。)

   ♠ \spadesuit 以传值的方式,给函数传递一个对象或从函数返回一个对象,也将调用拷贝构造函数;

C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第13张图片
注意:
  拷贝构造函数的参数,必须传引用,不能传值!!!
  如果拷贝构造函数的参数用传值的方式,那么当实参传递给拷贝构造函数的时候,拷贝构造函数的形参,为了复制实参,则又需要调用拷贝构造函数,即调用它自己,于是形成死循环。

补充:拷贝赋值函数(赋值运算符重载)

  下面的代码将调用赋值运算符重载:

  classT object;//创建一个对象
  classT another_object;//创建另一个对象
  object=another_object;//把一个对象赋值给另一个对象

补充:析构函数

C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第14张图片
例2:拷贝构造函数示例
C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第15张图片
附例2代码:

//小问学编程
#include
using namespace std;

class Vector
{
public:
    Vector(int s=0);
    Vector(int*,int);
    Vector(const Vector& v);
    ~Vector(){dispose();}
    int get_size()const {return size;}
    const Vector& operator=(const Vector& x);
    int& operator[](int index){return rep[index];}
    const int& operator[](int index)const{return rep[index];}
private:
    int* rep;
    int size;
    void clone(const Vector& a);
    void dispose();
};

void Vector::clone(const Vector& a)
{
    this->size=a.size;
    rep=new int[size];
    for(int count=0;count<size;++count)
        rep[count]=a[count];
}

void Vector::dispose()
{
    delete[] rep;
}

Vector::Vector(int s):size(s)
{
    if(size<=0)
        rep=NULL;
    else
    {
        rep=new int[size];
    for(int count=0;count<size;++count)
        rep[count]=0;
    }
}

Vector::Vector(int* a,int s):size(s),rep(new int[s])
{
    for(int count=0;count<size;++count)
        rep[count]=a[count];
}

Vector::Vector(const Vector& v)
{
    clone(v);
}

const Vector& Vector::operator=(const Vector&x)
{
    if(this!=&x)
    {
        delete[] rep;
        this->size=x.size;
        rep=new int[size];
        for(int count=0;count<size;++count)
            rep[count]=x[count];
    }
    return *this;
}

ostream& operator<<(ostream& os,const Vector& x)
{
    int s=x.get_size();
    for(int i=0;i<s;++i)
        os<<x[i];
    os<<endl;
    return os;
}

bool operator==(const Vector& a,const Vector& b)
{
    bool yes=true;
    if(a.get_size()!=b.get_size())
        yes=false;
    else
    {
        int s=a.get_size(),index=0;
        while(index<s&&a[index]==b[index])
            ++index;
        if(index<s)
            yes=false;
    }
    return yes;
}

int main()
{
    Vector vec1;
    cout<<vec1<<endl;

    int array[5]={1,2,3,4,5};
    Vector vec2(array,5);
    cout<<vec2<<endl;

    Vector vec3(vec2);
    cout<<vec3<<endl;

    if(vec3==vec2)
    {
        cout<<"The vector3 is equal to vector2"<<endl;
    }
    Vector vec4;
    vec4=vec3;
    cout<<vec4<<endl;
    return 0;
}

例3:构造函数析构函数调用示例
C++之Big Three:拷贝构造、拷贝赋值、析构函数探究_第16张图片
附例3代码:

//小问学编程
#include
using namespace std;

class Demo
{
public:
    Demo(int n=0);//默认构造
    Demo(const Demo& a);//拷贝构造,参数必须传引用
    ~Demo();//析构函数
    const Demo& operator=(const Demo& a);//拷贝赋值
private:
    int i;
};

Demo::Demo(int n):i(n)//默认构造
{
    cout<<"default constructor called"<<endl;
}

Demo::Demo(const Demo& a)//拷贝构造
{
    i=a.i;
    cout<<"copy constructor called"<<endl;
}

Demo::~Demo(){cout<<"destructor called"<<endl;}//析构函数

const Demo& Demo::operator=(const Demo& a)//拷贝赋值
{
    this->i=a.i;
    cout<<"assignment operator used"<<endl;
    return *this;
}

//全局函数:传入一个临对象后,声明一个demo d,然后返回d的临时对象
Demo foo(Demo a){Demo d;return d;}

int main()
{
    Demo a(2);//调用默认构造
    {
        Demo b;//调用默认构造
        b=foo(a);//先调用了全局函数foo
        //a是一个对象,
        //foo(a)调用了拷贝构造,
        //然后调用默认构造,产生临时对象形成返回值
        //把foo(a)返回的对象给对象b调用了拷贝赋值
    }//调用了3次析构函数
    Demo c=a;//调用拷贝构造
    return 0;//调用了2次析构函数
}

你可能感兴趣的:(小问C++笔记,c++)