C++物件模型——解構語意學(第五章)

來源:互聯網
上載者:User

標籤:explicit   rtu   額外   style   模型   new   聲明   amp   程式   

5.4    對象的效率 (Object Efficiency)        在下面的效率測試中,物件建構和拷貝所須要的成本是以Point3d class聲明為基準,從簡單形式逐漸到複雜形式,包含Plain Ol‘ Data,抽象資料類型(ADT),單一繼承,多重繼承,虛擬繼承,下面函數是測試的主角:
Point3d lots_of_copies(Point3d a, Point3d b) {    Point3d pC = a;    pC = b;                // 1    b = a;                  // 2    return pC;}
    它內帶四個memberwise初始化操作,包含兩個參數,一個傳回值以及一個局部對象pC,它也內帶兩個memberwise拷貝操作,各自是1和2的pC和b.main()函數例如以下:
main() {    Point3d pA(1.725, 0.875, 0.478);    Point3d pB(0.315, 0.317, 0.838);    Point3d pC;    for (int iters = 0; iters < 10000000; iters++)        pC = lots_of_copies(pA, pB);    return 0;}
    在最初兩個程式中,資料類型是一個 struct 和一個擁有 public 資料的 class;
struct Point3d { float x, y, z; };
class Point3d { public: float x, y, z; };
    對pA和pB的初始化操作是通過 explicit initialization list來進行的:
Point3d pA = {1.725, 0.875, 0.478};
Point3d pB = {0.315, 0.317, 0.838};
    這兩個動作表現出bitwise copy語意,所以應該能夠預期它們的運行有最好的效率.
    "memberwise"初始化操作和拷貝操作(Initialization and Copy): Public Data Members和Bitwise Copy Semantics.
    CC的效率比較好,是由於NCC迴圈中產生了六個額外的組合語言指令.這個額外負擔並不會反映出不論什麼特定的C++語意,這兩個編譯器的"中間C輸出"大致是相等的.

5.5    解構語意學 (Semantics of Destruction)     假設 class 未定義destructor,那麼僅僅有在 class 內帶的member object(或是 class 自己的base class) 擁有destructor的情況下,編譯器才會自己主動合成出一個.否則,destructor會被視為不須要,也就不需被合成(當然更不須要被調用).比如,Point,預設情況下就沒有被編譯器合成出一個destructor--儘管它擁有一個 virtual function:
class Point {public:    Point(float x = 0.0, float y = 0.0);    Point(const Point &);    virtual float z();private:    float _x, _y;};
    類似的道理,假設把兩個Point對象組合成一個Line class:
class Line {public:    Line(const Point &, const Point &);    virtual draw();protected:    Point _begin, _end;};
    Line也不會擁有一個合成出來的destructor,由於Point並沒有destructor.
    當從Point派生出Point3d(即便是一種虛擬派生關聯)時,假設沒有聲明一個destructor,編譯器就沒有必要合成一個destructor.
    不論Point或Point3d,都 不須要destructor,為它們提供一個destructor反而不符合效率.應該拒絕那種"對稱策略"的想法:"已經定義了一個constructor,所以感覺必須提供一個destructor".其實,應該"須要"而非"感覺"來提供destructor,更不要由於不確定是否須要一個destructor,於是就提供它.
    為了決定 class 是否須要一個程式層面的destructor(或是constructor),請想想一個 class object的生命在哪裡結束(開始)?

須要什麼操作才幹保證對象的完整?

這是敲代碼時比較須要瞭解的.這也是constructor和destructor什麼時候起作用的關鍵.比如,已知:

{    Point pt;    Point *p = new Point3d;    foo(&pt, p);    delete p;}
    能夠看到,pt和p在作為foo()函數的參數之前,都必須先初始化為某些座標值.這時候須要一個constructor,否則使用者必須明白地提供座標值. 一般而言,class 的使用者沒辦法檢驗一個local變數或heap變數以知道它們是否被初始化.把constructor想象為程式的一個額外負擔是錯誤的, 由於它們的工作有其必要性.假設沒有它們,抽象化的使用就會有錯誤的傾向.
    當明白地 delete 掉p時會怎樣呢?在不論什麼程式上必須處理的嗎?

是否須要在 delete 之前這麼做:

p->x(0);p->y(0);
    不, 當然不須要.沒有不論什麼理由說明在 delete 一個對象之前先得將其內容清除乾淨.也不須要歸還不論什麼資源.在結束pt和p的生命之前,沒有不論什麼"class使用者層面"的程式操作是絕對必要的,因此,也就不一定須要一個destructor.
    然而考慮Vertex class,它維護了一個由緊鄰的"頂點"所形成的鏈表,而且當一個頂點的生命結束時,在鏈表上來回移動以完畢刪除操作.假設這正是程式猿所須要的,那這就是Vertex destructor的工作.
    當從Point3d和Vertex派生出Vertex3d時,假設不供應一個 explicit Vertex3d destructor,那麼還是希望Vertex destructor被調用,以結束一個Vertex3d object.因此,編譯器必須合成一個Vertex3d destructor,其唯一的任務就是調用Vertex destructor.假設提供一個Vertex3d destructor,編譯器會擴充它,使它調用Vertex destructor.一個由程式猿定義的destructor被擴充的方式類似constructors被擴充的方式,但順序相反:
     1.假設object內帶一個vptr,那麼首先重設(reset)相關的 virtual table.
    2.destructor的函數本身如今被運行,也就是說vptr會在程式猿的碼運行前被重設(reset).
    3.假設 class 擁有member class objects,而後者擁有destructors,那麼它們會以聲明順序的相反順序被調用.
    4.假設有不論什麼直接的(上一層)nonvirtual base classes擁有destructor,它們會以其聲明順序的相反順序被調用.
    5.假設有不論什麼的 virtual base classes擁有destructor,而當前討論的這個 class 是最尾端(most-derived)的 class,那麼它們會以其原來的構造順序的相反順序被調用
.
    (這個順序似乎有問題,應該為2,3,1,4,5.當中1在2,3之後)
    就像constructor一樣, 眼下對於destructor的一種最佳實現策略就是維護兩份destructor實體:
    1.一個complete object實體,總是設定好vptr,並調用 virtual base class destructors.
    2.一個base class subobject實體:除非在destructor函數中調用一個 virtual function,否則它絕不會調用 virtual base class destructors並設定vptr.

    一個 object的生命結束於其destructor開始運行之時, 因為每個base class destructor都輪番被調用,所以derived class 實際上變成了一個完整的object.比如一個PVertex對象歸還其記憶體空間之前,會依次變成一個Vertex3d對象,一個Vertex對象,一個Point3d對象,最後成為一個Point對象.當在destructor中調用member functions時,對象的蛻變會由於vptr的又一次設定(在每個destructor中,在程式猿所提供的代碼之前)而受到影響.在程式中實施destructor的真正語言將在第6章詳述.

C++物件模型——解構語意學(第五章)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.