1. 程式人生 > >C++筆記 第三十六課 經典問題解析三---狄泰學院

C++筆記 第三十六課 經典問題解析三---狄泰學院

如果在閱讀過程中發現有錯誤,望評論指正,希望大家一起學習,一起進步。
學習C++編譯環境:Linux

第三十六課 經典問題解析三

1.關於賦值的疑問

什麼時候需要過載賦值操作符?編譯器是否提供預設的賦值操作?
編譯器為每個類預設過載了賦值操作符
預設的賦值操作符僅完成淺拷貝
當需要進行深拷貝時必須過載賦值操作符
賦值操作符與拷貝建構函式有相同的存在意義

36-1 預設賦值操作符過載

#include <iostream>
#include <string>
using namespace std;
class Test
{
    int* m_pointer;
public:
    Test()
    {
        m_pointer = NULL;
    }
    Test(int i)
    {
        m_pointer = new int(i);
}
//自定義拷貝建構函式
    Test(const Test& obj)
    {
        m_pointer = new int(*obj.m_pointer);/*從堆空間申請一片記憶體,這片記憶體代表int型別的值,取值引數物件point指標所指向的堆空間中的整型值,將整個整型值取出來,並且賦值到新申請的這片記憶體空間去,這樣完成拷貝建構函式的操作*/
}
//賦值操作符過載函式原型,返回值型別一定是一個引用,為了連續賦值
//引數必須是const型別的引用型別
//賦值操作不是自賦值
//返回當前物件
    Test& operator = (const Test& obj)
    {
        if( this != &obj )
        {
            delete m_pointer;
            m_pointer = new int(*obj.m_pointer);
        }
        
        return *this;//返回當前物件
    }
    void print()
    {
        cout << "m_pointer = " << hex << m_pointer << endl;
    }
    ~Test()
    {
        delete m_pointer;
    }
};
int main()
{
    Test t1 = 1;
    Test t2;
    
    t2 = t1;
    
    t1.print();
    t2.print();
    
    return 0;
}

問題分析
在這裡插入圖片描述
一般性原則
過載複製操作符,必然需要實現深拷貝!!!
IntArray 陣列類的優化

2.不積跬步無以至千里

編譯器預設提供的函式
在這裡插入圖片描述

class Test                         //類
{
public:
Test();                       //無參建構函式---與類同名的成員函式
Test(const Test&);              //拷貝建構函式
Test& operator = (const Test&);   //賦值操作符過載函式
~Test();                      //預設解構函式
}

面試題目:如果只是定義了一個類,那裡面是不是空的呢?
雖然什麼都沒有不是,因為編譯器會為空的類放一些東西,就是四個函式實現。

3.關於string的疑問

下面的程式碼輸出什麼?為什麼?
在這裡插入圖片描述

36-2 字串問題1

//產生野指標
#include <iostream>
#include <string>
using namespace std;
int main()
{
    string s = "12345";
    const char* p = s.c_str();
        
    cout << p << endl;     
        
    s.append("abced");  //出現錯誤的原因: p成為了野指標
        
    cout << p << endl;     
    return 0;
}
執行結果
12345
12345abced

問題分析
在這裡插入圖片描述
string物件內部維護了一個指向資料的char*指標,這個指標可能在程式執行的過程中發生改變。
下面的程式輸出什麼?為什麼?
在這裡插入圖片描述

36-3 字串問題2

正確的程式碼:
#include <iostream>
#include <string>
using namespace std;
int main()
{
    const char* p = "12345";
    string s = "";
     
    s.reserve(10);  
    for(int i=0; i<5; i++)
    {
        s[i] = p[i];
    }
 
    if( !s.empty() )
    {
	cout << s << endl;
    }
    for(int i=0; i<5; i++)
    {
	cout << s[i] << endl;
    }
    return 0;
}
執行結果
1
2
3
4
5
錯誤的程式碼:
#include <iostream>
#include <string>
using namespace std;
int main()
{
    const char* p = "12345";
    string s = "";
     
    s.reserve(10);  
//下面for迴圈執行結束後m_length=0沒有改變,所以之後輸出為空
    for(int i=0; i<5; i++)
    {
        s[i] = p[i];
    }
	cout << s << endl;
    return 0;
}
執行結果為空

問題分析
在這裡插入圖片描述
小結
在需要進行深拷貝的時候必須過載賦值操作符
賦值操作符和拷貝建構函式有同等重要的意義
string類通過一個數據空間儲存字元資料
string類通過一個成員變數儲存當前字串的長度
C++開發時儘量避開C語言中慣用的程式設計思想