1. 程式人生 > >C/C++(C++拷貝構造器,賦值運算符重載)

C/C++(C++拷貝構造器,賦值運算符重載)

拷貝構造 避免 運算 目的 strlen 沒有 成員 fine 這樣的

拷貝構造器

由己存在的對象,創建新對象。也就是說新對象,不由構造器來構造,而是由拷貝構造器來完成。拷貝構造器的格式是固定的。

class 類名
{
    類名(const 類名 & another)
    拷貝構造體
}
class A
{
    A(const A & another)
    {}
}

規則:

1 系統提供默認的拷貝構造器。一經實現,不復存在。
2 系統提供的時等位拷貝,也就是所謂的淺淺的拷貝。
3 要實現深拷貝,必須要自定義。
4 淺拷貝,會導致內存重析構。linux下淺拷貝會掛機。double free,在有些情況下(含有堆空間的時候),要實現自拷貝構造

#include <iostream>
#include "mystring.h"

using namespace std;

int main()
{
    string s = "assassin";
    string ss(s);
    cout<<"++++++++++++++++"<<endl;
    cout<<ss<<endl;
    cout<<"++++++++++++++++"<<endl;

    mystring s1 = "intelwisd";
    mystring ss1(s1);//淺復制,兩個對象指向同一個地址空間,釋放對象的時候釋放了兩次對象所指向的地址空間。
cout<<"++++++++++++++++"<<endl; cout<<ss1.c_str()<<endl; cout<<"++++++++++++++++"<<endl; string sss = s; mystring sss1 = s1;//也可以實現,本質也是拷貝,用已有一個對象完成一個對象,從無到有的創建過程。 string ssss; ssss = s; mystring ssss1; ssss1 = s1;//默認的也可以,本質是賦值運算符重載---> this指針。
return 0; }
#ifndef MYSTRING_H
#define MYSTRING_H


class mystring
{
public:
    //mystring();
    mystring(const char *s = NULL);//無參的形式包含在裏面
    char * c_str();
    mystring(const mystring & another);
    ~mystring();
private:
    char * _str;
};

#endif // MYSTRING_H
#include<iostream>
#include "mystring.h"
#include "string.h"
using namespace std;


mystring::mystring(const char *s)
{
    if(s == NULL)
    {
        _str = new char[1];
        *_str = \0;
    }else{
        int len = strlen(s);
        _str = new char[len+1];
        strcpy(_str,s);
    }

}

char * mystring::c_str()
{
    return _str;
}
mystring::mystring(const mystring & another)
{
    //_str = another._str;//同類之間沒有隱私,這樣的淺復制會造成內存重析構。
    int len = strlen(another._str);
    _str = new char[len+1];
    strcpy(_str,another._str);
}

mystring::~mystring()
{
    delete []_str;
}

this 指針

系統在創建對象時,默認生成的指向當前對象的指針。這樣作的目的,就是為了帶來方便。

作用

1,避免構造器的入參與成員名相同。
2,基於 this 指針的自身引用還被廣泛地應用於那些支持多重串聯調用的函數中。

class Stu
{
    public:
    Stu(string name,int age)
    {
        this->name = name;
        this->age = age;
    }
    void display()
    {
        cout<<name<<"+++"<<age<<endl;
    }
    Stu & growUp()
    {
        this->age++;
        return *this;
    }
    private:
    string name;
    int age;
}
int main()
{
    Stu s("assassin",23);
    dout<<"&s:"<<&s<<endl;
    s.display();
    s.growUp().growUp().growUp().growUp().display();//年齡增加

    return 0;
}

賦值運算符重載(Operator=)

用一個己有對象,給另外一個己有對象賦值。兩個對象均己創建結束後,發生的賦值行為。
格式:

類名
{
    類名& operator=(const 類名& 源對象)
    拷貝體
}
class A
{
    A& operator=(const A& another)
    {
    //函數體
        return *this;
    }
};

規則:

1 系統提供默認的賦值運算符重載,一經實現,不復存在。
2 系統提供的也是等位拷貝,也就淺拷貝,會造成內存泄漏,重析構。
3 要實現深深的賦值,必須自定義。
4 自定義面臨的問題有三個:

1,自賦值
2,內存泄漏
3,重析構。
5 返回引用,且不能用 const 修飾。a = b = c => (a+b) = c

mystring & mystring::operator=(const mystring & another)
{
    if(this == &another)//復制自己的情況
        return *this;
    delete []this->_str;//先把自己的釋放掉
    int len = strlen(another._str);
    this->_str = new char [len+1];
    strcpy(this->_str,another._str);

    return *this;
}

完整代碼:

#include<iostream>
#include "mystring.h"
#include "string.h"
using namespace std;


mystring::mystring(const char *s)
{
    if(s == NULL)
    {
        _str = new char[1];
        *_str = \0;
    }else{
        int len = strlen(s);
        _str = new char[len+1];
        strcpy(_str,s);
    }

}

char * mystring::c_str()
{
    return _str;
}
mystring::mystring(const mystring & another)
{
    //_str = another._str;//同類之間沒有隱私,這樣的淺復制會造成內存重析構。
    int len = strlen(another._str);
    _str = new char[len+1];
    strcpy(_str,another._str);
}

mystring::~mystring()
{
    delete []_str;
}
mystring& mystring:: operator=(const mystring & another)
{
    if(this == &another)//復制自己的情況
        return *this;
    delete []this->_str;//先把自己的釋放掉
    int len = strlen(another._str);
    this->_str = new char [len+1];
    strcpy(this->_str,another._str);

    return *this;
}
#ifndef MYSTRING_H
#define MYSTRING_H


class mystring
{
public:
    //mystring();
    mystring(const char *s = NULL);//無參的形式包含在裏面
    char * c_str();
    mystring(const mystring & another);
    mystring& operator=(const mystring & another);
    ~mystring();
private:
    char * _str;
};

#endif // MYSTRING_H
#include <iostream>
#include "mystring.h"

using namespace std;

int main()
{
    string s = "assassin";
    string ss(s);
    cout<<"++++++++++++++++"<<endl;
    cout<<ss<<endl;
    cout<<"++++++++++++++++"<<endl;

    mystring s1 = "intelwisd";
    mystring ss1(s1);//淺復制,兩個對象指向同一個地址空間,釋放對象的時候釋放了兩次對象所指向的地址空間。
    cout<<"++++++++++++++++"<<endl;
    cout<<ss1.c_str()<<endl;
    cout<<"++++++++++++++++"<<endl;
    string sss;
    sss = s;

    mystring sss1;//
    sss1 = s1;

    return 0;
}

C/C++(C++拷貝構造器,賦值運算符重載)