先看一個例子。首先,我要寫一個vector;其次,為了使用方便,我需要提供一個帶 size 參數的構造函數。要求就這兩點。
那么,勢必要:
class vector
{
public:
vector(size_t size)
{
// ...
m_pData = new int[size]; // 假設就是 int 這樣的基本類型好了,以避免下面可能出現的離題
// ...
}
};
問題來了。new 不是有可能失敗嗎?失敗了在老編譯器里會返回 NULL(這個情形也先無視),在新編譯器里會拋異常。那么,在這里要不要進行檢查呢?如果檢查:
try
{
m_pData = new int[size];
}
catch (...)
{
}
catch到了。那么在這里可以干啥呢?似乎。。。啥也干不了!作為構造函數,沒法使用返回值,自然只能使用異常來提示外界;既然本來就是異常,我又何必在這里 try 一次呢?(假設這里沒有其他錯誤要處理,也假設這里的類型是int之類的基本類型,不會出現執行元素的構造函數失敗的情形)
既然這里的 try 讓我們如此無奈,那么就不必 try 了。這個時候,我需要給 vector(size_t size) 標記上 throw 嗎?如果不標記,使用者怎么知道這里可能會有異常?如果標記了,或者沒標記但使用者意識到了,那么他會這樣用:
try
{
vector v(10);
// Task with v
// ...
// ...
// ...
}
catch (...)
{
// Error handler
}
因為 v 的作用域被限制在了 try 內,所以所有的與 v 相關的邏輯代碼全部要放在 try 內部了。這種樣子似乎與 C# 很像!在 C# 里,try...catch... 是標準的做法;但是在 C++ 里,似乎不會如此經常地用 try catch,要不然,為什么我見過的 C++ 代碼都不是這樣子的呢?兩年前在金山實習的時候,有一次我把 try...catch 當做通用的錯誤處理來做,所有的錯誤都搞成一種異常,返回值僅返回正常值。結果董波叔叔說,這樣子是不對滴,但是沒給出讓我信服理由,可能就是,C++ 的 try...catch 的性能很不好之類的。(C# 以及 Java 的 try...catch 的性能好嗎?)
好,既然大家都不這么辦,是不是這里也不用 try 了?于是,內存分配錯誤就讓它自生自滅了……記得以前某本書上看到,說這種情形下的處理,僅僅是一個道德問題而已。真的無解嗎?
如果放寬要求,不要求在構造函數提供內存分配,那倒是有一種解法——分兩階段構造:
class vector
{
public:
vector()
{
// ...
}
bool allocate(size_t size)
{
try
{
m_pData = new int[size];
}
catch (...)
{
return false;
}
if (m_pData == NULL)
{
return false;
}
// Other code ...
return true;
}
};
但是使用起來就不“方便”了。現實中,這種情形倒是存在,如 CWindow 的 Create,還有啥啥啥的 Init 等等。
真的沒有辦法兼顧方便與安全嗎?
posted on 2010-03-30 22:31
溪流 閱讀(2384)
評論(15) 編輯 收藏 引用 所屬分類:
C++