C++帶指針的類的注意點

/**
 做者: cwl
 內容:
        帶指針類的注意點
        c++構造函數,拷貝構造,拷貝賦值
        new delete解析

*/
#include <bits/stdc++.h>

using namespace std;

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

    ///拷貝構造,接受本身這種東西的引用
    String(const String& str) {
        m_data = new char[strlen(str.m_data) + 1];
        strcpy(m_data, str.m_data);
    }

    ///拷貝賦值,接受本身這種東西的引用
    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;
    }

    ~String() {
        delete[] m_data;
    }

    char* get_c_str() const {
        return m_data;
    }
private:
    char* m_data;
};

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

int main() {

    /**
        c++中類四個重要部分
        構造函數
        析構函數
        拷貝構造
        拷貝賦值
    */

    ///[1] 若是你的class若是帶着指針,就必須重寫拷貝構造和拷貝賦值
    /**
        構造和析構是帶指針的類必備的,而容易被忽略的是下面兩個部分。

        【1.1】拷貝構造

        String(const String& str) {
            m_data = new char[strlen(str.m_data) + 1];
            strcpy(m_data, str.m_data);
        }
        可能會有疑問,str中的m_data明明是private爲何能直接訪問?
        答:解釋有不少,其中一個是一個類的不一樣對象互爲友元

        【1.2】拷貝賦值

        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;
        }

        殺掉原來的,建立一個同大小的空間,返回。
        細節是要檢測是不是檢測自我賦值。
        if(this == &str) {
            return *this;
        }
        多想一步,增強代碼穩定性。


        下面咱們添加輸出
        inline ostream&
        operator << (ostream& os, const String &str) {
            os << str.get_c_str();
            return os;
        }
    */
    String a = "hello";
    cout << a << endl;

    /**
        堆和棧
        【1】String a("qqq");
                a是棧空間,有操做系統建立在做用域{}結束後釋放。
                自動,auto,也就是舊的時候的auto語義,c++11前的
        【2】String *p = new String("asd");
                p在棧空間,執行了new處理的堆空間。須要手動delete
                不然會出現[內存泄漏]
        【3】static int a;
                聲明週期擴展被擴張
        【4】全局對象
                生命在main以前,main結束後才析構
    */

    ///【new】new 會先申請內存,轉形,而後調用構造函數
    ///new 的過程
    ///注:operator new是一個函數的名字,c++中能查到源代碼

    /**
        String *pc;
        void* mem = operator new(sizeof(String));   申請空間
        pc = static_cast<String*>(mem);             類型轉化
        pc->String::String("asd");    調用構造函數,直接調會有問題,這裏只是示例

    */

    ///【delete】delete的過程
    /// String::~String(ps)     //析構函數
    /// operator delete(ps)     //釋放內存

    /**
        new 和 delete 底層使用malloc和delete得到空間

    */

    return 0;
}
相關文章
相關標籤/搜索