1)在適用構造函數建立對象時,有時會建立臨時對象。如數組
Stock::Stock(const std::string & co,long n,double pr);函數
在使用時,下面兩條語句有根本區別:指針
Stock stock2=Stock("Boffo Ojects",2,2.0);對象
stock1=Stock("Nifty Foods",10,50.0); stock1是類對象內存
第一條語句是初始化,它建立有指定值的對象,可能會建立臨時對象(也可能不會,取決於實現,個人電腦不會建立);第二條語句是賦值。像這樣在賦值語句中使用構造函數總會致使在賦值前建立一個臨時對象。若是既能夠經過初始化,也能夠經過賦值來設置對象的值,則應採用初始化方式。一般這種方式的效率更高。作用域
2)做用域爲類的常量字符串
有時,類聲明可能使用字面值30來指定數組的長度,因爲該常量對於全部對象來講都是相同的,所以建立一個由全部對象共享的常量是個不錯的主意。但下面這樣作不可行:編譯器
class Bakerystring
{it
const int Months=12;
double costs[Months];
...
};
這是由於聲明類只是描述了對象的形式,並無建立對象。所以,在建立對象前,將沒有用於存儲值的空間(C++11提供了成員初始化,但不適用於前述數組聲明)。有兩種方式能夠實現這個目標,而且效果相同
第一種:在類中聲明一個枚舉。在類聲明中聲明的枚舉的做用域爲整個類,所以能夠用枚舉爲整型常量提供做用域爲整個類的符號名稱。能夠這樣聲明:
class Bakery
{
enum{Months=12};
double costs[Months];
....
}
用這種方式聲明枚舉並不會建立類數據成員。也就是說,全部對象中都不包含枚舉。Months只是一個符號名稱,在做用域爲整個類的代碼中遇到它時,編譯器將用12來替換。
第二種:使用關鍵字static。
class Bakery
{
static const int Months=12;
double costs[Months];
...
}
這將建立一個名爲Months的常量,該常量與其它靜態變量存儲在一塊兒,而不是存儲在對象中
3)符號常量和常變量的區別
符號常量不佔用內存空間,在預編譯時就所有由符號常量的值替換了,因爲不佔有內存空間,故不可對符號常量尋址,enum聲明的就是符號常量,而const int Months=12,聲明的爲一常變量,由於可對Months尋址。
而常變量首先它是變量,佔有內存空間,但其值必須在聲明時初始化,且其值不可更改,const聲明的是常變量,而不是如C++ Primer Plus的3.2節所說的符號常量
4)C++ Primer Plus中程序11_16的一些思考
在11_16中,有一個符號常量Lbs_per_stn。它的由來可參看書中10.6節,它還能夠替換爲static const int Lbs_per_stn=14;在看到12.7節中聲明瞭一個類Queue,其中有一個const int qsize成員變量(其實就是常量)。它採用成員初始化列表給常量賦值,即在執行構造函數體以前,建立對象時進行初始化。
Queue::Queue(int qs):qsize(qs)
{
front=rear=null;
items=0;
}
那麼在程序11_16中,是否也能夠採用這種方式,將Lbs_per_stn聲明爲const int,在構造函數中採用成員初始化列表呢?
class Stonewt
{
const int Lbs_per_stn;
.....
};
Stonewt::Stonewt(double n):Lbs_per_stn(14)
{
......
}
經試驗,在11_16中,不能採用這種方式,由於程序中有語句incognito=275;它的工做方式爲先調用Stonewt(double)構造函數建立一個臨時對象,再採用編譯器自動生成的operator=()函數將臨時對象的值逐成員複製到incognito中,而const int incognito屬於成員變量,它已在生成對象時初始化爲14;const變量是不能再被賦值的;故在編譯時會出現operator=()函數在Stonewt中不可用致使錯誤。
若程序中沒有incognito=275;則這種採用成員初始化列表的方式是可用的。
總結:若想採用把一個對象賦值給另外一個對象,則成員變量中必不能出現常變量const,由於它只可初始化,不能再次被賦值。而enum{Months=12};則是定義了一個符號常量,在編譯時,編譯器會自動把Months替換爲12;而static const int Lbs_per_stn=14;則是定義了一個名爲Months的常量,該常量爲靜態,與其它靜態變量存儲在一塊兒,而不是存儲在對象中,故此時也可利用=賦值。
5)指針和數組名的區別
char * p="abcdefg";和char str[]="abcdefg";str和指針p都指向字符串的首地址,這一點沒有區別。可是,str給字符串"abcdrfg"分配了內存空間,該字符串存儲在該內存空間中,可是p指針並無爲字符串分配內存空間,字符串"abcdefg"在內存中的存儲由系統分配,指針p在32位機中只佔有4個字節,即全部指針類型的佔用空間單位。此時,指針p指向的時字符串常量"abcdefg",能夠改變指針指向的值,但不能爲指針賦值。如
char *ps=p+4;
char *pt=p+2;
*pt='L'; (1)
*pt++=*ps++; (2)
其中(1)和(2)是不能夠賦值的,雖然編譯時沒有錯誤,由於"abcdefg"對p來說是一個字符串常量。可是,在這種賦值對數組來講是能夠的
char str[]="abcdefg";
char *ps=p+4;
char *pt=p+2;
*pt='L'; (3)
*pt++=*ps++; (4)
(3)和(4)都是能夠正常運行的。 必定要注意指針和數組的區別!!!!
(6)函數參數傳遞問題
在傳遞函數參數時,若未聲明爲引用,則是按值傳遞,即便參數爲指針。這裏必定要區分參數爲指針和參數爲數組的區別!!!數組名做爲參數時,也是地址,但此時對數組的操做是對原來數組的操做,這並不違反按值傳遞的原則,傳遞時,函數生成一個與數組名類型相同的指針,數組名把值傳遞給該指針,這步就是按值傳遞,只是該指針也指向原數組的內存空間,因此是對原數組進行操做。指針做爲函數參數時,也是按值傳遞的,在內存中會有兩個指針變量,他們指向同一塊內存區。!!!