程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 《深度探索C++對象模型》讀書筆記(6)

《深度探索C++對象模型》讀書筆記(6)

編輯:關於C++

***對象的構造和解構***

一般而言,我們會把object盡可能放置在使用它的那個程序區段附近,這樣做可以節省不必要的對象 產生操作和銷毀操作。

***全局對象***

全局對象的靜態初始化策略包括以下幾個步驟:

(1)為每一個需要靜態初始化的對象產生一個_sti_……()函數,內含必要的 constructor調用操作或inline expansions;

(2)為每一個需要靜態的內存釋放操作的對象產生一個_std_……()函數,內含必要 的destructor調用操作或inline expansions;

(3)在main()函數的首尾分別添加一個_main()函數(用以調用可執行文件中的所有_sti()函 數)和一個_exit()函數(用以調用可執行文件中的所有_std()函數)。

建議根本不要用那些需要靜態初始化的全局對象。

***局部靜態對象***

假設我們有以下程序片段:

const Matrix& identity() {
static Matrix mat_identity;
// ...
return mat_identity;
}

此處的local static class object保證了以下語意:

(a)mat_identity的constructor必須只能施行一次,雖然上述函數可能會被調用多次;

(b)mat_identity的destructor必須只能施行一次,雖然上述函數可能會被調用多次。

編譯器的實際做法如下:在第一次調用identity()時把mat_identity構造出來,而在與相應文件關 聯的靜態內存釋放函數中將其解構。(局部靜態對象的地址在downstream component中將會被轉換到程 序內用來放置global object的data segment中)

***對象數組***

如果你想要在程序中取出一個constructor的地址,這是不可以的。然而經由一個指針來激活 constructor,將無法存取default argument values.那麼,如何支持以下的語句:

complex::complex(double=0.0, double=0.0);

當程序員寫出:

complex c_array[10];

時,編譯器最終需要調用:

vec_new(&c_array,sizeof(complex),10,&complex::complex,0);

為了解決這個問題,可由編譯器產生一個內部的constructor,沒有參數,在其函數內調用由程序員 提供的constructor,並將default參數值明確地指定過去:

complex::complex()
{
complex(0.0, 0.0);
}

***new和delete運算符***

以constructor來配置一個class object:

Point3d *origin = new Point3d;

被轉換為:

Point3d *origin;
if(origin = _new(sizeof(Point3d))){
try {
origin = Point3d::Point3d(origin);
}
catch( ... ) {
_delete(origin);  // 釋放因new而配置的內存
throw;  // 將原來的exception上傳
}
}

如果我們配置一個數組,內帶10個Point3d objects,我們預期Point和Point3d的constructor被調用 各10次,每次作用於數組中的一個元素:

// 完全不是好主意
Point *ptr = new Point3d[10];

如果我們進行如下的釋放操作:

// 只有Point::~Point被調用
delete []ptr;

由於其觸發的vec_delete()是通過迭代走過每一個數組元素,而本例中被傳遞過去的是Point class object的大小而不是Point3d class object的大小,整個運行過程將會失敗。

解決之道在於程序層面,而非語言層面:

for(int ix = 0; ix < 10; ix++)
{
Point3d *p = &((Point3d*)ptr)[ix];
delete p;
}

當然,最好還是避免以一個base class指針指向一個derived class objects所組成的數組。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved