11:構造函數中,分配的動態內存對象,需要delete
~Hasptr() { delete ps; }//必須首先delete對象ps,ps指向一個動態分配的string12:知識點:當指向一個對象的引用或者指針離開作用域是,析構函數并不會執行
析構函數執行三次:accum,item1,item2
13:
#include<iostream> #include<string> #include<fstream>#include<list>#include<vector> #include<map> #include<set>#include<cctype>//ctype無法打開,包含tolower()函數和ispunct函數#include<algorithm>#include<utility>//保存pair的頭文件#include<memory>using namespace std;class A{public: A(int m):val(m)//默認構造函數 { cout<<"默認構造函數"<<endl; } A& Operator= (const A& a) //拷貝賦值運算符 { val = a.val; cout<<"拷貝復制運算符"<<endl; return *this; } ~A()//析構函數 { cout<<"析構函數"<<endl; } int val;};void show1(A& a){ cout<<a.val<<endl;}void show2(A a){ cout<<a.val<<endl;}int main(int argc, char**argv) { //將A的對象當作引用或者非引用傳遞 A a(10); A b(5); A c(2); c = a; show1(a); show2(b); show2(c); //存放于容器中 vector<A> m; m.push_back(a); //動態分配 A *d = new A(5); show2(*d); delete d; return 0;}14:知識點:這五種操作通常被視為一個整體,一般來說都會一起出現
知識點2:需要析構函數的類也需要拷貝和賦值操作,合成的析構函數不會delete一個指針數據成員,所以有時我們需要自己定義一個析構函數釋放構造函數分配的內存,所以需要析構函數的類,也就需要拷貝構造函數和拷貝賦值運算符,而合成的拷貝構造函數和拷貝賦值運算符只能簡單的拷貝指針成員,這就意味著多個對象指向同一個內存,釋放多個對象時,造成多次delete
知識點3:如果一個類需要自定義版本的析構函數,那么肯定是需要自定義的拷貝構造函數和拷貝賦值運算符
知識點4:拷貝操作和復制操作是相互結合的,如果需要一種,也需要另一種,但不一定意味著需要析構函數
會輸出三個一樣的數字,合成的拷貝構造函數只是簡單的進行拷貝
15:使用了自定義版本的合成構造函數,生成新的序號,那么肯定輸出就是三個不一樣的數字了
16:函數的參數變為引用版本的形參,無需拷貝,結果改變,但輸出仍為三個不一樣的數字
17:
#include<iostream> #include<string> #include<fstream>#include<list>#include<vector> #include<map> #include<set>#include<cctype>//ctype無法打開,包含tolower()函數和ispunct函數#include<algorithm>#include<utility>//保存pair的頭文件#include<memory>using namespace std;class A{public: A()//默認構造函數,14題 { static int val1 = 10; val = val1++; } A(A &a)//自定義版本的拷貝構造函數 { val = a.val+5; } int val;};void show2(A a){ cout<<a.val<<endl;}void show3(const A& a){ cout<<a.val<<endl;}int main(int argc, char**argv) { A a, b = a, c = b; show2(a);//調用函數時需要拷貝一次 show2(b); show2(c);// show3(a);//這里的調用不需要拷貝構造運算符// show3(b);// show3(c); return 0;}18:知識點1:我們可以通過將拷貝控制成員定義為 =default 來顯式的要求編譯器生成合成的版本(只能對有合成版本的函數使用),在此之后,合成的函數將隱式的聲明為內聯
知識點2:iostream類阻止了拷貝,避免多個對象同時寫入,或讀取相同的IO緩沖,我們可以將拷貝構造函數和拷貝賦值運算符定義為刪除的函數來阻止拷貝,雖然聲明了他們,但不能以任何的方式使用他們,在參數列表之后加上 =delete 來指出我們希望其是被刪除的,這是為了通知編譯器,我們不希望這些函數被定義
知識點3:可以對任何類內函數(析構函數除外)聲明 =delete ,且必須出現在函數第一次聲明的時候,如果析構函數被聲明=delete ,析構函數被刪除,就無法銷毀此類型的對象
知識點4:本質上,當不可能拷貝、賦值、銷毀類的成員時,類的拷貝構造函數會被定義為刪除的
知識點5:C++11之前,是將拷貝構造函數和拷貝賦值運算符定義為PRivate來阻止拷貝的(舊標準)
見下方19題:
19:拷貝控制成員:拷貝構造函數和拷貝賦值運算符
#include<iostream> #include<string> #include<fstream>#include<list>#include<vector> #include<map> #include<set>#include<cctype>//ctype無法打開,包含tolower()函數和ispunct函數#include<algorithm>#include<utility>//保存pair的頭文件#include<memory>using namespace std;//具體操作時將類的聲明置于頭文件中class Employee{public: Employee();//默認構造函數 Employee(string& s);//接受一個string的構造函數 Employee(const Employee&) =delete;//不需要拷貝構造函數,怎么可能有人一樣。將其聲明為 =delete Employee& operator= (const Employee&) =delete; int number(){return _number;}private: string employee; int _number; static int O_number;//static靜態成員數據在類內聲明,但只可以在類外定義,在類外定義時可不加static};int Employee::O_number = 0;Employee::Employee()//默認構造函數{ _number = O_number++;}Employee::Employee(string& s)//接受一個string的構造函數{ employee = s; _number = O_number++;}void show(Employee a){ cout<<a.number()<<endl;}int main(int argc, char**argv) { Employee a, b, c; show(a);//調用函數時需要拷貝一次 show(b); show(c); return 0;}20:
TextQuery和QueryResult所有成員(包括智能指針和容器)都將被拷貝
新聞熱點
疑難解答
圖片精選