初值化(Initial)和給定數值(Assign)
(a) 什麼是initial?變數宣告的時候,直接給了數值,像是:
int a=10;
(b)什麼是Assign?
變數宣告完後,再另外給定數值,像是:
int a;
a=10;
這兩種寫法有差異嗎? 對build-in類型,像是int, float, ...沒有差別,但是對物件而言,就決定了一點點效能上的差別了,我以一個類別A來解釋:
class A
{
}; // 什麼事都沒有的類別
使用assign你必須先宣告一個物件 A a;
此時,物件已經執行了一次建構式,把內部數值初始一次,你也許會問,類別中沒有建構式啊?何來呼叫建構式? 答案是,類別雖然沒有設計建構式,但是C++標準中有幾個函式你不需要寫,C++都會幫你生出來,而你寫了,就不會幫你產生,分別是:
預設建構式: A::A(){}
複製建構式: A::A(const A &a ){}
解構式: A::~A(){}
指定運算元: A::operator =( const A& a ){}
所以當你下A a;a=b;這樣的程式時,已經執行了一次建構式,之後再一行assign,物件又會執行一次"指定運算元",所以你跑了兩次物件的函式。
而Initial呢? 看起來A a=b; 這樣的程式碼,同樣是執行一次建構式,然後再執行一次指定運算元?答案是,編譯器直接執行複製建構式,所有數值一次搞定,比起Assign快了一倍,也許不多,但是,如果你的物件內部,變數數量超多,一個assign需要執行的指令碼很多,那也許就有點可觀了:)
說到建構式,也許有人會問,他看過以下兩種程式碼,有差別嗎?
A::A()
: a(120), c(0.3)
{
}
A::A()
{
a=120;
c=0.3;
}
答案依照結果論而言,沒有差別,但是同樣潛在一點點效能上的差別,首先第一種方法A()後面接著的":a(...." 那行稱為 "member initializer list",專供給物件內成員變數的初值化,與呼叫基底類別的建構式所用,在這個時候,物件的記憶體還在配置中,C++會一邊配置記憶體,一邊把你指定的數值塞進去,所以,變數給定數值的次數只有一次,而下面那種A::A(){ ... } 的方式呢? 此時記憶體已經配置完成,變數數值已經給定過了一次,而此時又再設定一次,所以跑了兩次數值給定的程序,所以會慢一滴滴。
member initializer list這麼好用,有什麼限制嗎?
有的,指定順序要跟變數宣告的順序一致,原因說過,C++會一邊配置記憶體,一邊給定數值,如果順序不對,以下的程式就可能出錯:
class A
{
vector
int size;
A() : buf(size), size(20)
....
};
你希望配置大小為size的vector
class A
{
int size;
vector
A() : size(20), buf(size)
....
};
沒有留言:
張貼留言