一,概念
1)靜態儲存方式:指在程式運行期間分配固定的儲存空間的方式。外部變數和靜態變數屬於此種儲存方式
2)靜態成員變數:為該類的所有執行個體所共用,也就是說當某個類的執行個體修改了該靜態成員變數,其修改值為該類的其它所有執行個體所見。無論建立多少對象,程式都只建立一個靜態變數副本。
3)靜態成員特點:靜態成員存在於記憶體,非靜態成員需要執行個體化才會分配記憶體,所以靜態成員不能訪問非靜態成員..因為靜態成員存在於記憶體,所以非靜態成員可以直接存取類中靜態成員。
4)不能在類聲明中初始化靜態成員變數,因為聲明描述了如何分配記憶體,但並不分配記憶體。
5)delete/new
new char[ ]/delete [ ] 成對出現
6)new 建立對象後,再用delete
刪除對象可以釋放對象本身佔用的記憶體。但並不能自動釋放屬於對象成員的指標指向的記憶體。
#include <iostream>#include <cstring>using namespace std;class StringBad{private: char *str; int len; static int num_strings;public: StringBad(const char *s); StringBad(); ~StringBad(); friend ostream &operator<< (ostream &os,const StringBad &st);};StringBad::StringBad(const char* s){ len=strlen(s); str=new char[len+1]; strcpy(str,s); num_strings++; cout<<num_strings<<":\""<<str<<"\""<<"object created\n";}StringBad::StringBad(){ len=4; str=new char[4]; strcpy(str,"C++"); num_strings++; cout<<num_strings<<":\""<<str<<"\""<<"object created\n";}StringBad::~StringBad(){ --num_strings; cout<<"\""<<str<<"\""<<"object deleted\n"; cout<<num_strings<<"left\n"; delete [] str;} ostream & operator<< (ostream &os,const StringBad &st)//must add const{ os<<st.str; return os;}int StringBad::num_strings=0;void callme(StringBad &);//非成員函數void callme(StringBad &rab){ cout<<"string passed by reference:"; cout<<"\""<<rab<<"\"\n";}int main(){ StringBad headline1("tianshuai"); StringBad headline2("is a good student"); StringBad sports("he do good job"); cout<<"headline1:"<<headline1<<endl; cout<<"headline2:"<<headline2<<endl; cout<<"sports:"<<sports<<endl; callme(headline1); return 0;}
輸出:
1:"tianshuai"object created2:"is a good student"object created3:"he do good job"object createdheadline1:tianshuaiheadline2:is a good studentsports:he do good jobstring passed by reference:"tianshuai""he do good job"object deleted2left"is a good student"object deleted1left"tianshuai"object deleted0left
二,建構函式
1)預設建構函式:顯示定義建構函式即無參數建構函式,如果有參數建構函式所有參數都有預設值
2)複製建構函式:當使用者沒有定義自已的複製建構函式時系統將產生一個預設的複製建構函式。當按值傳遞對象時,就會建立一個形參的臨時對象,然後調用複製建構函式把臨時對象的值複製給實參。
功能:將一個對象的非靜態成員的值逐個複製給另一個對象,注意複製的是成員的值,這種複製方式也稱為淺複製。因為靜態成員屬於整個類,而不屬於某個對象,所以調用複製建構函式時靜態成員不會受到影響。
何時使用:按值傳遞對象,函數返回對象,用一個對象初始化另一個對象即複製初始化時,根據元素初始化列表初始化數組元素。這四種情況都將調用複製建構函式。記住,複製建構函式只能用於初始化,不能用於賦值,賦值時不會調用複製建構函式,而是使用賦值操作符。
3)解析複製建構函式:s1=s2;
s1.str=s2.str;//這裡s1複製的不是字串而是指向字串的指標
s1.len=s2.len;
當s2的解構函式被調用時,釋放str指向的記憶體delete
[ ]s2.str。則s1出現問題
解決辦法:深度複製
StringBad::StringBad(const
StringBad &st)
{
len=st.len;
str=new
char[len +1 ]; //關鍵使用new 動態申請存放字串的記憶體
strcpy(str,st.str)
}
4)理解賦值與複製初始化的區別(重點):賦值是在兩個已存在的對象間進行的,也就是用一個已存在的對象去改變另一個已存在對象的值。賦值將調用賦值操作符對對象進行操作,賦值操作符將在操作符重載中講解。比如有類hyong,有語句hyong
x(1);hyong y(1,2)則x=y;這就是賦值,因為對象x和y是已經存在的對象,而語句hyong x=y;則是複製初始化,是用一個已存在的對象y去建立一個新對象x,所以是複製初始化。
三,改進string
1)strcmp(const char *s1,const char * s2)
當s1<s2時,傳回值<0
當s1=s2時,傳回值=0 當s1>s2時,傳回值>0
2)靜態方法:靜態方法與靜態變數一樣,屬於類本身,而不屬於那個類的一個對象。要想調用一個被定義為static的方法,必須在它前面加上這個類的名稱。
使用規則:靜態方法只能訪問類的靜態成員,不能訪問類的非靜態成員;
非靜態方法可以訪問類的靜態成員,也可以訪問類的非靜態成員;
靜態方法不能使用執行個體來調用,只能使用類名來調用。
3)布局new操作符:在分配記憶體時 指定已存在的記憶體位置。在已知數組中再申請適當大小地區
char *buffer=new
char[512];
p1 = new (buffer)JustTesting;
p2 = new (buffer
+ sizeof(JustTesting))JustTesting("tian",5);
delete [ ] buffer;不調用p1,p2解構函式
delete p1; 釋放buffer而不是
p1
p1->~JustTesting();