C++對象特殊初始化及賦值

  在閱讀一些C++源碼的時候,我們會發現給對象初始化或賦值時用有類似“ClassA a = {1,2}”或“a = {1,2}(a是對象)”的語句。這種初始化以及賦值的表達形式讓人產生疑惑:首先,它是如何給對象賦值的;其次,這種表達是不是需要ClassA有特殊的實現。這些都令人疑惑。
  網絡上有人把這種賦值形式解釋爲ClassA類重載了賦值操作符。但是真實情況並非如此。這篇文章將對C++對象初始化以及賦值時的這種特殊用法進行一個簡單的說明以及實驗驗證。
  
  首先觀察下面的例子:

#include <iostream>
using namespace std;

template<class T, std::size_t N> 
class array 
{
    public:
        T elems[N];
        template <typename T2>
        array<T,N>& operator= (const array<T2,N>& rhs) 
        {
            cout << "operator =" << endl;
            return *this;
        }
        int &operator[](int n)
        {
            return elems[n];
        }
        int size(){return sizeof(elems)/sizeof(T);}
};

int main()
{
    array<int,6> a = {1,2,3,4,5,6};
    int sizes = a.size();
    for(int i = 0; i < sizes; i++)
        cout << a[i] << " ";
    cout << endl;
    cout << sizeof(a) << endl;

    return 0;
}

  在這個例子中有兩個類array和btest,array就是我們常用的容器,因此作爲一個數組的對象,我們希望它可以像基本數據結構那樣去初始化。上面的代碼可以正常運行,而且我們可以通過測試看到,執行結果,並沒有使用賦值運算符函數。這就證明網絡上說的跟賦值運算符重載是錯誤的。

再寫一個例子:

#include <iostream>
using namespace std;

class btest
{   
public: 
    void print()
    {   
        cout << "a = " << a << " b= " << b << " c = " << c << endl;
    }
public:
    char a;
    int b;
    double c;
};

int main()
{
    btest b = {'p',56,82.342};
    btest c = b;
    b.print();
    c = {'q', 23, 43.23};
    c.print();
    return 0;
}

  這個例子,我們通過大括號的初始化方式,成功將btest類的對象b初始化,依次對對象b中的成員變量進行了賦值,使得{a,b,c}={’p’,56,82.342};而接下來的變量c,在C++98標準的編譯器下,對其執行賦值操作會報錯,在支持C++11即C++0x標準時,就可以正常編譯運行。另外,當btest類中的成員變量改爲private的時候,任何編譯器都不能編譯通過。
  這就引起我們的思考,我們都知道在C++中struct關鍵字和class關鍵字在語義上有很大的相通之處:1.struct也可以定義類,只是類中的默認成員都是public的;2.struct中也可以包括成員方法,這一點與類很相似;3.struct也可以在定義體中加private關鍵字,以強調成員對外隱藏。而struct結構體變量如果進行”structA a = {1, 3}”這樣的初始化,大家就不會有太大的疑惑了。
  另外,要理解對象在內存中的存儲結構。我們都知道,類的方法是被其對象所共享的,而類的成員變量則是各自擁有,因此對象的大小通常是對象的成員變量所佔的內存大小;因此,其在初始化對象或賦值對象的時候,右值中大括號裏的內容就會像結構體初始化一樣,直接賦值到對象所佔內存的成員變量中。
  還有一種需要注意到的情況就是,當類中定義有虛擬函數的時候,虛擬函數會使對象所在內存空間位於起始位置的地方保存虛表,這時這種初始化以及賦值的方法就會失效,因爲這樣就會有非法的數據寫到虛表所在內存空間,造成虛表錯誤。因此,無法編譯通過。
  到這裏,我想這個問題說明清楚了。可能有什麼紕漏,希望大家指正。

發佈了29 篇原創文章 · 獲贊 9 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章