日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

effective C++ 条款 21:必须返回对象时别妄想返回其reference

發(fā)布時(shí)間:2025/3/20 c/c++ 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 effective C++ 条款 21:必须返回对象时别妄想返回其reference 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

考慮有理數(shù)的class:

class Rational
{
public:
??? Rational(int numerator = 0, int denominator = 1);
protected:
private:
??? int n, d;
??? friend Rational operator*(const Rational& lhs, const Rational& rhs);
};

by value版的operator*, 你可能想改而返回reference,以根除pass-by-value的種種邪惡,省掉構(gòu)造和析構(gòu),但是,

所謂reference只是個(gè)名稱,代表某個(gè)既有對(duì)象,任何時(shí)候看到一個(gè)reference聲明式,你都應(yīng)該立刻問(wèn)自己,它的另一個(gè)名稱是什么?

如果operator*要返回一個(gè)reference指向如此數(shù)值,他必須自己創(chuàng)建那個(gè)Rational對(duì)象。

const Rational& operator*(const Rational& lhs, const Rational& rhs)
{
??? Rational result(lhs.n * rhs.n, lhs.d * rhs.d); //警告!糟糕的代碼!
??? return result;
}

你的目標(biāo)是要避免調(diào)用構(gòu)造函數(shù),而result卻必須像任何對(duì)象一樣地由構(gòu)造函數(shù)構(gòu)造起來(lái)。更嚴(yán)重的是result是一個(gè)local對(duì)象,而local對(duì)象在函數(shù)退出前被銷(xiāo)毀了。因此這個(gè)返回的reference指向的是一個(gè)“從前的”Rational;如今已經(jīng)被銷(xiāo)毀了。任何調(diào)用者甚至對(duì)此函數(shù)的返回值做任何一點(diǎn)點(diǎn)運(yùn)用,都會(huì)陷入“無(wú)定義行為”的惡地。

于是考慮在heap內(nèi)構(gòu)造一個(gè)對(duì)象, 并返回reference指向它。

const Rational& operator*(const Rational& lhs, const Rational& rhs)
{
??? Rational* result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d); //更糟的代碼!
??? return *result;
}

你還是必須付出一個(gè)構(gòu)造函數(shù)調(diào)用的代價(jià),此外又有另一個(gè)問(wèn)題:誰(shuí)該對(duì)著被你new出來(lái)的對(duì)象實(shí)施delete?

Rational w, x, y, z;

w = x * y * z; //與operator*(operator*(x, y), z)相同

同一個(gè)語(yǔ)句調(diào)用了兩次operator*, 因而兩次使用new,也就需要兩次delete。但卻沒(méi)有合理的辦法讓operator*使用者進(jìn)行delete調(diào)用, 因?yàn)闆](méi)有合理的辦法讓他們?nèi)〉給perator*返回的reference背后隱藏的那個(gè)指針。這絕對(duì)導(dǎo)致資源泄漏。

或許你想到一種辦法可以避免任何構(gòu)造函數(shù)被調(diào)用。“讓operator*返回reference指向一個(gè)被定義于函數(shù)內(nèi)部的static Rational對(duì)象

const Rational& operator*(const Rational& lhs, const Rational& rhs)
{
??? static Rational result; //又是一堆爛代碼。
??? result = ...; //lhs*rhs
??? return result;
}

就像所有用上static對(duì)象的設(shè)計(jì)一樣, 這個(gè)也立刻造成我們對(duì)多線程安全性的疑慮。只是顯而易見(jiàn)的弱點(diǎn)。更深層的瑕疵:

bool operator=(const Rational& lhs, const Rational& rhs);
Rational a, b, c, d;
if ((a*b) == (c*d)){
??? ...
}else{
??? ...
}

表達(dá)式if ((a*b) == (c*d))總是被核算為true, 不論a,b, c,d是什么。

在operator==被調(diào)用前,已有兩個(gè)operator*調(diào)用式起作用,每個(gè)都返回operator*內(nèi)部定義的static Rational對(duì)象的reference,這個(gè)將“operator*內(nèi)的static Rational對(duì)象值”和“operator*內(nèi)的static Rational對(duì)象值”比較,不相等才怪。(雖然兩次調(diào)用operator*都改變了static Rational對(duì)象的值, 但是返回的reference, 調(diào)用端看到的永遠(yuǎn)是static Rational的現(xiàn)值)。

一個(gè)“必須返回新對(duì)象”的函數(shù)的正確寫(xiě)法:就讓那個(gè)函數(shù)返回一個(gè)新對(duì)象。

inline const Rational operator*(const Rationa& lhs, const Rational& rhs)

{

??? return Rational(lhs.n * rhs.n, lhs.d * rhs.d);

}

絕不要返回pointer或reference指向一個(gè)local stack對(duì)象, 或返回reference指向一個(gè)heap-allocated對(duì)象, 或返回pointer或reference指向一個(gè)local static對(duì)象而有可能同時(shí)需要多個(gè)這樣的對(duì)象。條款4已經(jīng)為“在單線程環(huán)境中合理返回reference指向一個(gè)local static對(duì)象”提供了一份設(shè)計(jì)實(shí)例(singleton)

轉(zhuǎn)載于:https://www.cnblogs.com/lidan/archive/2012/01/17/2325108.html

總結(jié)

以上是生活随笔為你收集整理的effective C++ 条款 21:必须返回对象时别妄想返回其reference的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。