C語言確實很優雅,整個語言的設計簡潔一致。而在C++中,有一個讓人詬病的問題就是變量初始化的不一致性。
C語言中的初始化,都是用花括號進行,簡單美觀:
int array[] = {1,2,3,4,5};
struct Point point = {2, 3};
struct Point arrPoint[] =
{
{2,3},
{4,5},
{6,7}
};
struct Point point = {2, 3};
struct Point arrPoint[] =
{
{2,3},
{4,5},
{6,7}
};
C++自然也兼容了C語言的初始化機制。然而,C++的Class乃至STL都不支持。它們要用不同的方式來初始化, 甚至根本不能夠直接初始化, 只能使用運行時的賦值。
比如Class:
class Param
{
public:
int Age;
int Value;
private:
int Level;
};
Param param = {2,3}; // ERROR
Param param = {2,3,4}; //ERROR
無法初始化。而如果不初始化的話,所有的成員而處于無政府狀態,這顯然很不讓人放心。于是,C++提供了專門用于Class的初始化方式--構造函數:{
public:
int Age;
int Value;
private:
int Level;
};
Param param = {2,3}; // ERROR
Param param = {2,3,4}; //ERROR
class Param
{
public:
Param(int x, int y)
: x_(x), y_(y)
{}
Param()
: x_(0), y_(0)
{}
private:
int x_, y_;
};
Param param(1,2);
//或
Param param;
有了構造函數,可以在構造函數的初始化列表中對成員進行初始化。可是很明顯,這里頭還是有一個陷阱,默認構造初始化和非默認構造初始化的調用方式是不一致的。默認構造函數不能用括號來調用,否則編譯器將會發瘋:{
public:
Param(int x, int y)
: x_(x), y_(y)
{}
Param()
: x_(0), y_(0)
{}
private:
int x_, y_;
};
Param param(1,2);
//或
Param param;
Param param();
它會把上面的語句看成是函數聲明,而后面調用的時候就會出錯,而錯誤信息可能會讓你抓狂一下。但是這樣也就算了,偏偏 new 可以接受有括號和沒括號兩種寫法:

再比如STL容器,這下好象更慘,連構造函數都幫不上忙了,除了初始化一個空的容器,或是復制一下別的容器,我們只能做用默認構造函數進行初始化。我們拿數組和vecotr做個比較:
// 數組
int arr[]={1,2,3,4};
// vector
vector<int> iarr;
// 必須在某個函數中賦初值
void init()
{
for(int i = 1; i <= 4; ++i)
iarr.push_back(i);
}
int arr[]={1,2,3,4};
// vector
vector<int> iarr;
// 必須在某個函數中賦初值
void init()
{
for(int i = 1; i <= 4; ++i)
iarr.push_back(i);
}
再復雜一點的數據結構,那單單賦值程序就要寫上老長,而且還不好看。還要記得調用。這對于僅僅是簡單的設置一些初值的用途來說,太過于煩瑣。
橫向比較,這次好象C++還不會太落伍,只有C和動態語言提供了初始化特性,其它支持OO高級語言好象都是學C++的。如Java, C#(注C#3.0開始提供初始化功能)...
C++能不能做到簡潔一致的實始化呢?
Boost的assign庫做了許多有益的工作。使用assign庫,至少現在可以初始化了:











C++0x已確定提供與C一致的初始化功能。 Initialer lists Initializer Lists for Standard Containers Initializer lists WP wording 等草案就是為了這個目的服務的。
如果使用C++0x,那么程序的初始化將變得清晰和一致:
complex<double> z = {1,2};
//或
complex<double> z {1,2};
// 初始化中,有等號和無等號都是允許的,下同。
z += {2,3};
int a = {1};
new vector<string>{"once", "upon", "a", "time"};
f( {"Nicholas", "Annemarie"} ); // 參數是兩個元素的列表
return { "Norah" }; // 返回只有一個元素的列表
int* e {}; // 初始化為0或NULL指針
map<string,int> anim =
{
{"bear",4},
{"cassovary",2},
{"tiger",7}
};
//或
complex<double> z {1,2};
// 初始化中,有等號和無等號都是允許的,下同。
z += {2,3};
int a = {1};
new vector<string>{"once", "upon", "a", "time"};
f( {"Nicholas", "Annemarie"} ); // 參數是兩個元素的列表
return { "Norah" }; // 返回只有一個元素的列表
int* e {}; // 初始化為0或NULL指針
map<string,int> anim =
{
{"bear",4},
{"cassovary",2},
{"tiger",7}
};
這好象是C++欠了十多年的債吧。