鄭州網(wǎng)站開發(fā)比較好的網(wǎng)絡(luò)公司網(wǎng)絡(luò)營銷管理
文章目錄
- 1.賦值運算符重載
- 1.1 運算符重載
- 1.2 賦值運算符重載
- 2.取地址重載
- 2.1 const成員函數(shù)
- 2.2 取地址運算符重載
- 3.類與對象的補充
- 3.1 再探構(gòu)造函數(shù)---初始化列表
- 3.2 類型轉(zhuǎn)換
- 3.3 static成員
- 3.4 友元
- 3.5 內(nèi)部類
- 3.6 匿名對象
- 3.7 對象拷貝時的編譯器優(yōu)化
1.賦值運算符重載
賦值運算符重載是六個默認(rèn)成員函數(shù)之一,在講解這個我們要先了解一下運算符重載。
1.1 運算符重載
當(dāng)運算符被用于類類型的對象時,C++語言允許我們通過運算符重載的形式指定新的含義。C++規(guī)定類類型對象使用運算符的時候,必須轉(zhuǎn)換成調(diào)用對應(yīng)運算符重載,若沒有對應(yīng)的運算符重載,則會報編譯錯誤。
注意:對于下面的例子中,都是使用的Date類。
class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << '-' << _month << '-' << _day << endl;}private:int _year;int _month;int _day;
};
- 運算符重載是具有特別名字的函數(shù),他的名字是由operator和后面要定義的運算符共同構(gòu)成。和其他函數(shù)一樣,他也具有其返回類型和參數(shù)列表以及函數(shù)體。
- 重載運算符函數(shù)的參數(shù)個數(shù)和該運算符作?的運算對象數(shù)量?樣多。?元運算符有?個參數(shù),?元運算符有兩個參數(shù),?元運算符的左側(cè)運算對象傳給第?個參數(shù),右側(cè)運算對象傳給第?個參數(shù)。(注意:成員函數(shù)的第一個參數(shù)默認(rèn)是this指針。)
示例:
如果我們寫了這行代碼,那么毫無疑問編譯器會報錯,因為對于類類型判斷相等的符號編譯器是無法識別的(只有內(nèi)置類型才可以使用):
那么我們就需要寫一個賦值運算符重載了,如下:
Q1:上面的代碼為什么會報錯?
A1:我們是定義了一個全局函數(shù),而類內(nèi)的成員變量是私有的,即類外是無法訪問的。
Q2:我們?nèi)绾谓鉀Q上面錯誤呢?
A2:我們有四個方法:
- 成員變?yōu)楣?#xff08;不建議,不安全)
- Date提供GetYear之類的函數(shù)
- 使用友元函數(shù)(之后會介紹)
- 重載為成員函數(shù)(推薦,下面第3點就會講到)
- 如果?個重載運算符函數(shù)是成員函數(shù),則它的第?個運算對象默認(rèn)傳給隱式的this指針,因此運算符重載作為成員函數(shù)時,參數(shù)?運算對象少?個。
示例:
- 運算符重載以后,其優(yōu)先級和結(jié)合性與對應(yīng)的內(nèi)置類型運算符保持?致。
- 不能通過連接語法中沒有的符號來創(chuàng)建新的操作符:?如operator@。
- ?個類需要重載哪些運算符,是看哪些運算符重載后有意義,?如Date類重載operator-就有意義(兩個日期相減得到天數(shù)),但是重載operator+就沒有意義(兩個日期相加沒有意義)。
- 重載++運算符時,有前置++和后置++,運算符重載函數(shù)名都是operator++,?法很好的區(qū)分。C++規(guī)定,后置++重載時,增加?個int形參,跟前置++構(gòu)成函數(shù)重載,?便區(qū)分。
- 重載<<和>>時,需要重載為全局函數(shù),因為重載為成員函數(shù),this指針默認(rèn)搶占了第?個形參位置,第?個形參位置是左側(cè)運算對象,調(diào)?時就變成了 對象<<cout,不符合使?習(xí)慣和可讀性。重載為全局函數(shù)把ostream/istream放到第?個形參位置就可以了,第?個形參位置當(dāng)類類型對象。
示例:
//流插入
ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}//流提取
istream& operator>>(istream& in, Date& d)
{cout << "請依次輸入年月日:>";in >> d._year >> d._month >> d._day;return in;
}
Q:為什么返回值要是ostream&和istream&?
A:因為我們他的對象是為了讓他支持連續(xù)輸入輸出 的特性,對于&是因為流插入和流提取是不允許被修改的。
對于上面的講解,下面我會依次給出例子:
示例①:重載運算符+和+=
// d1 += 50
Date& Date::operator+=(int day)
{if (day < 0){return *this -= (-day);}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 13){_year++;_month = 1;}}return *this;
}// d1 + 50
Date Date::operator+(int day)
{Date tmp(*this);tmp._day += day;while (tmp._day > GetMonthDay(tmp._year, tmp._month)){tmp._day -= GetMonthDay(tmp._year, tmp._month);tmp._month++;if (tmp._month == 13){tmp._year++;tmp._month = 1;}}return tmp;
}
由于每月的天數(shù)不一樣,并且閏年的二月會少一天,所以定義GetMonthDay是獲取某年某月的天數(shù),如下:
int GetMonthDay(int year, int month)
{static int day[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && (year % 4 == 0 && year % 100 != 0) && year % 400 == 0)return 29;return day[month];
}
但是對于上面的重載運算符+和+=,其實我么你只需要實現(xiàn)一個就可以了,另外一個只需要通過已經(jīng)重載的那個運算符來使用它即可,如下是兩種不同重載對比:
我們可以發(fā)現(xiàn),我們先重載運算符+=,在用+=就可以間接使用運算符重載+,這樣的效率更高,只需要調(diào)用兩次拷貝構(gòu)造。
示例②:同上,重載運算符-和-=
// d1 -= 50
Date& Date::operator-=(int day)
{if (day < 0){return *this += (-day);}_day -= day;while(_day <= 0){//借位--_month;if (_month == 0){--_year;_month = 12;}_day += GetMonthDay(_year, _month);}return *this;
}// d1 - 50
Date Date::operator-(int day)
{Date tmp = *this;tmp -= day;return tmp;
}
示例③:重載運算符>(大于)
// >
bool Date::operator>(const Date& d)
{if (_year > d._year)return true;else if (_year == d._year && _month > d._month)return true;else if (_year == d._year && _month == d._month)return _day > d._day;return false;
}
示例④:運算符重載==(等于)
// ==
bool Date::operator==(const Date& d)
{return _year == d._year&& _month == d._month&& _day == d._day;
}
有了>和==運算符重載,可以衍生如下運算符重載:
- 大于等于
// >=
bool Date::operator>=(const Date& d)
{return *this > d || *this == d;
}
- 小于
// <
bool Date::operator<(const Date& d)
{return !(*this >= d);
}
- 小于等于
// <=
bool Date::operator<=(const Date& d)
{return !(*this >= d);
}
- !=
// !=
bool Date::operator!=(const Date& d)
{return !(*this == d);
}
示例⑤:前置++和后置++
// 前置++
Date& Date::operator++()
{*this += 1;return *this;
}// 后置++
Date Date::operator++(int)
{Date tmp = *this;*this += 1;return tmp;
}
注意:對于前置++,我們返回的是Date&,因為前置++,自增之后,我們返回的是+1的值。而后置++,我們返回的是沒有+1之前的值,但是我們本身this指向的對象時自增了的。
1.2 賦值運算符重載
賦值運算符重載是?個默認(rèn)成員函數(shù),?于完成兩個已經(jīng)存在的對象直接的拷?賦值,這?要注意跟拷?構(gòu)造區(qū)分,拷?構(gòu)造?于?個對象拷?初始化給另?個要創(chuàng)建的對象。
賦值運算符的特點:
- 賦值運算符重載是?個運算符重載,規(guī)定必須重載為成員函數(shù)。賦值運算重載的參數(shù)建議寫成const 當(dāng)前類類型引?,否則會傳值傳參會有拷?。
- 有返回值,且建議寫成當(dāng)前類類型引?,引?返回可以提?效率,有返回值?的是為了?持連續(xù)賦值場景。
- 沒有顯式實現(xiàn)時,編譯器會?動?成?個默認(rèn)賦值運算符重載,默認(rèn)賦值運算符重載?為跟默認(rèn)構(gòu)造函數(shù)類似,對內(nèi)置類型成員變量會完成值拷?/淺拷?(?個字節(jié)?個字節(jié)的拷?),對?定義類型成員變量會調(diào)?他的賦值運算符重載。
- 像Date這樣的類成員變量全是內(nèi)置類型且沒有指向什么資源,編譯器?動?成的賦值運算符重載就可以完成需要的拷?,所以不需要我們顯?實現(xiàn)賦值運算符重載。像Stack這樣的類,雖然也都是內(nèi)置類型,但是_a指向了資源,編譯器?動?成的賦值運算符重載完成的值拷?/淺拷?不符合我們的需求,所以需要我們??實現(xiàn)深拷?(對指向的資源也進?拷?)。像MyQueue這樣的類型內(nèi)部主要是?定義類型Stack成員,編譯器?動?成的賦值運算符重載會調(diào)?Stack的賦值運算符重載,也不需要我們顯?實現(xiàn)MyQueue的賦值運算符重載。這?還有?個?技巧,如果?個類顯?實現(xiàn)了析構(gòu)并釋放資源,那么他就需要顯?寫賦值運算符重載,否則就不需要。(與拷貝構(gòu)造函數(shù)類似)
示例:
class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}Date(const Date& d){cout << " Date(const Date& d)" << endl;_year = d._year;_month = d._month;_day = d._day;}void Print(){cout << _year << '-' << _month << '-' << _day << endl;}// 傳引?返回減少拷?// d1 = d2;Date& operator=(const Date& d){// 不要忘記檢查??給??賦值的情況if (this != &d){_year = d._year;_month = d._month;_day = d._day;}// d1 = d2表達式的返回對象應(yīng)該為d1,也就是*thisreturn *this;}private:int _year;int _month;int _day;
};int main()
{Date d1(2024, 11, 28);Date d2(d1);Date d3(2024, 11, 11);d1 = d3;// 需要注意這?是拷?構(gòu)造,不是賦值重載// 請牢牢記住賦值重載完成兩個已經(jīng)存在的對象直接的拷?賦值// ?拷?構(gòu)造?于?個對象拷?初始化給另?個要創(chuàng)建的對象Date d4 = d1;return 0;
}
2.取地址重載
2.1 const成員函數(shù)
- 將const修飾的成員函數(shù)稱之為const成員函數(shù),const修飾成員函數(shù)放到成員函數(shù)參數(shù)列表的后面
- const實際修飾該成員函數(shù)隱含的this指針,表明在該成員函數(shù)中不能對類的任何成員進?修改。const 修飾Date類的Print成員函數(shù),Print隱含的this指針由 Date* const this 變?yōu)?const Date* const this
意思就是我們在成員函數(shù)的后面加上了const,就意味著不可以修改this指向的對象了。
注意:
- const對象必須調(diào)用const成員函數(shù),這是權(quán)限的平移
- const對象若調(diào)用非const成員函數(shù),會報錯誤,這是權(quán)限的放大
- 非const對象調(diào)用const成員函數(shù),是允許的,這是權(quán)限的縮小
2.2 取地址運算符重載
取地址運算符重載分為普通取地址運算符重載和const取地址運算符重載,?般這兩個函數(shù)編譯器?動?成的就可以夠我們?了,不需要去顯?實現(xiàn)。除??些很特殊的場景,?如我們不想讓別?取到當(dāng)前類對象的地址,就可以??實現(xiàn)?份,胡亂返回?個地址。
示例:
class Date
{
public :Date* operator&(){return this;// return nullptr;}const Date* operator&()const{return this;// return nullptr;}
private :int _year ; // 年int _month ; // ?int _day ; // ?
};
3.類與對象的補充
3.1 再探構(gòu)造函數(shù)—初始化列表
- 之前我們實現(xiàn)構(gòu)造函數(shù)時,初始化成員變量主要使?函數(shù)體內(nèi)賦值,構(gòu)造函數(shù)初始化還有?種?式,就是初始化列表,初始化列表的使??式是以?個冒號開始,接著是?個以逗號分隔的數(shù)據(jù)成員列表,每個"成員變量"后?跟?個放在括號中的初始值或表達式。
示例:
class Time
{
public:Time(int hour):_hour(hour) //初始化列表{cout << "Time()" << endl;}
private:int _hour;
};
- 每個成員變量在初始化列表中只能出現(xiàn)?次,語法理解上初始化列表可以認(rèn)為是每個成員變量定義初始化的地?。
- 引?成員變量,const成員變量,沒有默認(rèn)構(gòu)造的類類型變量,必須放在初始化列表位置進?初始化,否則會編譯報錯。
Q:為什么這三種情況必須在初始化列表進行初始化呢?
A:我們知道,①引用是不可以修改的,他不像指針可以修改,也不像指針初始化成空。在之前我們就提到過:引用必須初始化和不可以修改。②const修飾的成員變量是不可以進行修改的,他是一個常變量,存儲到內(nèi)存中的代碼段(只讀變量)。③對于自定義的類類型當(dāng)中還存在自定義的類類型,我們必須調(diào)用它的默認(rèn)構(gòu)造函數(shù),不然就會報錯。
示例:
class Time
{
public:Time(int hour):_hour(hour) //初始化列表{cout << "Time()" << endl;}
private:int _hour;
};class Date
{
public:Date(int& x, int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day), _t(12), _ref(x), _n(1){// error C2512: “Time”: 沒有合適的默認(rèn)構(gòu)造函數(shù)可?// error C2530 : “Date::_ref” : 必須初始化引?// error C2789 : “Date::_n” : 必須初始化常量限定類型的對象}void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;Time _t; // 沒有默認(rèn)構(gòu)造int& _ref; // 引?const int _n; // const
};int main()
{int i = 0;Date d1(i);d1.Print();return 0;
}
- C++11?持在成員變量聲明的位置給缺省值,注意:這個缺省值只是是給沒有顯?在初始化列表初始化的成員使?的。
- 盡量使?初始化列表初始化,因為那些你不在初始化列表初始化的成員也會?初始化列表,如果這個成員在聲明位置給了缺省值,初始化列表會?這個缺省值初始化。如果你沒有給缺省值,對于沒有顯?在初始化列表初始化的內(nèi)置類型成員是否初始化取決于編譯器,C++并沒有規(guī)定。對于沒有顯?在初始化列表初始化的?定義類型成員會調(diào)?這個成員類型的默認(rèn)構(gòu)造函數(shù),如果沒有默認(rèn)構(gòu)造會編譯錯誤。
示例:
class Time
{
public:Time(int hour):_hour(hour){cout << "Time()" << endl;}
private:int _hour;
};class Date
{
public:Date():_month(2){cout << "Date()" << endl;}void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}
private:// 注意這?不是初始化,這?給的是缺省值,這個缺省值是給初始化列表的// 如果初始化列表沒有顯?初始化,默認(rèn)就會?這個缺省值初始化int _year = 1;int _month = 1;int _day;Time _t = 1;const int _n = 1;int* _ptr = (int*)malloc(12);
};
int main()
{Date d1;d1.Print();return 0;
}
- 初始化列表中按照成員變量在類中聲明順序進?初始化,跟成員在初始化列表出現(xiàn)的的先后順序?關(guān)。建議聲明順序和初始化列表順序保持?致。
示例:下?程序的運?結(jié)果是什么()
A. 輸出 1 1
B. 輸出 2 2
C. 編譯報錯
D. 輸出 1 隨機值
E. 輸出 1 2
F. 輸出 2 1
class A
{
public:A(int a):_a1(a), _a2(_a1){}void Print() {cout << _a1 << " " << _a2 << endl;}
private:int _a2 = 2;int _a1 = 2;
};
int main()
{A aa(1);aa.Print();
}
所以這道題應(yīng)該選D,這道題還是很重要的。
3.2 類型轉(zhuǎn)換
- C++?持內(nèi)置類型隱式類型轉(zhuǎn)換為類類型對象,需要有相關(guān)內(nèi)置類型為參數(shù)的構(gòu)造函數(shù)
- 構(gòu)造函數(shù)前?加explicit就不再?持隱式類型轉(zhuǎn)換
示例:
class A
{
public:// 構(gòu)造函數(shù)explicit就不再?持隱式類型轉(zhuǎn)換// explicit A(int a1)A(int a1):_a1(a1){}//explicit A(int a1, int a2)A(int a1, int a2):_a1(a1),_a2(a2){}void Print(){cout << _a1 << " " << _a2 << endl;}private:int _a1 = 1;int _a2 = 2;
};int main()
{// 用1來構(gòu)造一個A的臨時對象,再用這個臨時對象拷貝構(gòu)造aa1// 編譯器優(yōu)化:遇到連續(xù)構(gòu)造+拷貝構(gòu)造 -> 優(yōu)化為直接構(gòu)造A aa1 = 1;aa1.Print();const A& aa2 = 1;// C++11之后開始支持多參數(shù)轉(zhuǎn)化A aa3 = { 2, 2 };return 0;
}
3.3 static成員
- ?static修飾的成員變量,稱之為靜態(tài)成員變量,靜態(tài)成員變量?定要在類外進?初始化。
示例:
class A
{
private:// 類內(nèi)聲明static int _scount;
};// 類外初始化
int A::_scount = 0;
- 靜態(tài)成員變量為所有類對象所共享,不屬于某個具體的對象,不存在對象中,存放在靜態(tài)區(qū)。
示例:對于上面的示例中,我們計算類A的大小:cout << sizeof(A) << endl;
輸出的結(jié)果是1,之前我們講過1是為了占位使用的。
- ?static修飾的成員函數(shù),稱之為靜態(tài)成員函數(shù),靜態(tài)成員函數(shù)沒有this指針。
- 靜態(tài)成員函數(shù)中可以訪問其他的靜態(tài)成員,但是不能訪問非靜態(tài)的,因為沒有this指針
示例:
- 非靜態(tài)的成員函數(shù),可以訪問任意的靜態(tài)成員變量和靜態(tài)成員函數(shù)。
- 突破類域就可以訪問靜態(tài)成員,可以通過類名::靜態(tài)成員 或者 對象.靜態(tài)成員 來訪問靜態(tài)成員變量和靜態(tài)成員函數(shù)。
- 靜態(tài)成員也是類的成員,受public、protected、private 訪問限定符的限制。
- 注意:靜態(tài)成員變量不能在聲明位置給缺省值初始化,因為缺省值是個構(gòu)造函數(shù)初始化列表的,靜態(tài)成員變量不屬于某個對象,不走構(gòu)造函數(shù)初始化列表。
示例:實現(xiàn)一個類,計算程序共創(chuàng)建了多少個類對象
class A
{
public:A(){++_scount;}A(const A& a){++_scount;}~A(){--_scount;}static int GetACount(){return _scount;}private:// 類內(nèi)聲明static int _scount;
};//類外初始化
int A::_scount = 0;int main()
{//靜態(tài)成員不屬于某個對象,可以直接通過類域訪問到cout << A::GetACount() << endl;A a1, a2;A a3(a1);cout << A::GetACount() << endl;cout << a1.GetACount() << endl;// 編譯報錯:error C2248: “A::_scount”: ?法訪問 private 成員(在“A”類中聲明)//cout << A::_scount << endl;return 0;
}
牛客網(wǎng)的一個例題,不允許使用各種循環(huán)和遞歸,實現(xiàn) 1 + 2 + 3 + … + n ?
我們可以通過創(chuàng)建類來實現(xiàn),創(chuàng)建第幾個類就讓他加上幾。示例:
class Sum
{
public:Sum(){_ret += _i;++_i;}static int GetRet(){return _ret;}
private:static int _i;static int _ret;
};int Sum::_i = 1;
int Sum::_ret = 0;class Solution
{
public:int Sum_Solution(int n) {//VS不支持邊長數(shù)組,會報錯Sum arr[n];return Sum::GetRet();}
};
注意:VS不支持邊長數(shù)組。
例題:有A、B、C、D四個類
C c;
int main()
{A a;B b;static D d;return 0;
}
A:D B A C
B:B A D C
C:C D B A
D:A B D C
E:C A B D
F:C D A B
Q1:程序中A,B,C,D構(gòu)造函數(shù)調(diào)用順序為?(E)
A1:這個很簡單
Q2程序中A,B,C,D析構(gòu)函數(shù)調(diào)?順序為?(B)
A2:這里要注意一點,static修飾的變量是存放在靜態(tài)區(qū)的,static修飾的變量生命周期會變長,即整個main函數(shù)棧幀銷毀才會銷毀D,所以輝縣析構(gòu)B和A,在析構(gòu)D,由于C是在全局變量中,所以最后析構(gòu)他(它是最先創(chuàng)建的,先創(chuàng)建的后析構(gòu))
3.4 友元
- 友元提供了?種突破類訪問限定符封裝的方式,友元分為:友元函數(shù)和友元類,在函數(shù)聲明或者類聲明的前?加friend(沒有要求,可放在public中也可以放在private中),并且把友元聲明放到?個類的里面。
- 友元函數(shù)可以在類定義的任何地方聲明,不受類訪問限定符限制。
- 外部友元函數(shù)可訪問類的私有和保護成員,友元函數(shù)僅僅是?種聲明,他不是類的成員函數(shù)。
- ?個函數(shù)可以是多個類的友元函數(shù)。
- 友元類中的成員函數(shù)都可以是另?個類的友元函數(shù),都可以訪問另?個類中的私有和保護成員。
- 友元類的關(guān)系是單向的,不具有交換性,?如A類是B類的友元,但是B類不是A類的友元。
- 友元類關(guān)系不能傳遞,如果A是B的友元, B是C的友元,但是A不是B的友元。
- 有時提供了便利。但是友元會增加耦合度,破壞了封裝,所以友元不宜多用。
友元函數(shù)示例:
// 前置聲明,否則A的友元函數(shù)聲明編譯器不認(rèn)識B
class B;class A
{// 友元聲明friend void func(const A& aa, const B& bb);
private:int _a1 = 1;int _a2 = 2;
};class B
{// 友元聲明friend void func(const A& aa, const B& bb);
private:int _b1 = 3;int _b2 = 4;
};void func(const A& aa, const B& bb)
{cout << aa._a1 << endl;cout << bb._b1 << endl;
}int main()
{A aa;B bb;func(aa, bb);return 0;
}
友元類示例:
class A
{// 友元聲明friend class B;
private:int _a1 = 1;int _a2 = 2;
};class B
{
public:void func1(const A& aa){cout << aa._a1 << endl;cout << _b1 << endl;}void func2(const A& aa){cout << aa._a2 << endl;cout << _b2 << endl;}
private:int _b1 = 3;int _b2 = 4;
};
int main()
{A aa;B bb;bb.func1(aa);bb.func2(aa);return 0;
}
3.5 內(nèi)部類
- 如果?個類定義在另?個類的內(nèi)部,這個內(nèi)部類就叫做內(nèi)部類。內(nèi)部類是?個獨?的類,跟定義在全局相?,他只是受外部類類域限制和訪問限定符限制,所以外部類定義的對象中不包含內(nèi)部類。
- 內(nèi)部類默認(rèn)是外部類的友元類
- 內(nèi)部類本質(zhì)也是?種封裝,當(dāng)A類跟B類緊密關(guān)聯(lián),A類實現(xiàn)出來主要就是給B類使?,那么可以考慮把A類設(shè)計為B的內(nèi)部類,如果放到private/protected位置,那么A類就是B類的專屬內(nèi)部類,其他地方都用不了。
示例:
class A
{
public:class B //B默認(rèn)就是A的友元{public:void func(const A& a){cout << _k << ' ' << a.h << endl;}};
private:static int _k;int h = 1;
};int A::_k = 1;int main()
{//輸出結(jié)果是4,所以內(nèi)部類是不占空間的cout << sizeof(A) << endl;A::B b; //實例化BA aa;b.func(aa);return 0;
}
我們把上面那個??途W(wǎng)的題目優(yōu)化一下:
class Solution
{
public:class Sum{Sum(){_ret += _i;_i++;}};
public:int Sum_Solution(int n){// 變長數(shù)組Sum arr[n];return _ret;}
private:static int _i;static int _ret;
};int Solution::_i = 1;
int Solution::_ret = 0;
這樣寫是不是更簡單、優(yōu)美了。
3.6 匿名對象
- 用類型(實參) 定義出來的對象叫做匿名對象,相比之前我們定義的 類型 對象名(實參) 定義出來的叫有名對象。
- 匿名對象?命周期只在當(dāng)前?行,?般臨時定義?個對象當(dāng)前用?下即可,就可以定義匿名對象。
示例:
class A
{
public:A(int a = 0):_a(a){cout << "A(int a = 0)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};class Solution
{
public:int Sum_Solution(int n) {return n;}
};int main()
{A aa1;//不可以這樣定義對象,因為編譯器?法識別下?是?個函數(shù)聲明,還是對象定義//這里VS沒有報錯,也沒有調(diào)用它的構(gòu)造和析構(gòu)函數(shù),說明編譯器把它當(dāng)做是函數(shù)聲明//A aa2();//但是我們可以這么定義匿名對象,匿名對象的特點不?取名字//但是他的?命周期只有這??,我們可以看到下??他就會?動調(diào)?析構(gòu)函數(shù)A();A(1);// 匿名對象在這樣場景下就很好?,當(dāng)然還有?些其他使?場景Solution().Sum_Solution(10);return 0;
}
3.7 對象拷貝時的編譯器優(yōu)化
- 現(xiàn)代編譯器會為了盡可能提?程序的效率,在不影響正確性的情況下會盡可能減少?些傳參和傳參過程中可以省略的拷?。
- 如何優(yōu)化C++標(biāo)準(zhǔn)并沒有嚴(yán)格規(guī)定,各個編譯器會根據(jù)情況??處理。當(dāng)前主流的相對新?點的編譯器對于連續(xù)?個表達式步驟中的連續(xù)拷?會進?合并優(yōu)化,有些更新更"激進"的編譯還會進?跨?跨表達式的合并優(yōu)化。
這一點未完待續(xù)!!!