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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

《C++面向对象高效编程(第2版)》——3.4 赋值操作符

發布時間:2025/3/21 c/c++ 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《C++面向对象高效编程(第2版)》——3.4 赋值操作符 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本節書摘來自異步社區出版社《C++面向對象高效編程(第2版)》一書中的第3章,第3.4節,作者: 【美】Kayshav Dattatri,更多章節內容可以訪問云棲社區“異步社區”公眾號查看。

3.4 賦值操作符

C++面向對象高效編程(第2版)
現在,讓我們分析main程序中的語句:

a = b ;  // 將一個棧賦值給另一個棧
在該語句中,我們將對象b賦值給對象a,使用賦值操作符完成賦值操作。如果a和b都是簡單的整數,無論a中的值是什么,編譯器都會用b中的值將其擦寫(overwrite)。就是這么簡單。但是在該例中,a和b都是我們創建的對象,這意味著由我們負責賦值操作。我們知道TIntStack類對象之間如何進行賦值,并且能夠實現賦值操作符。對于任何賦值操作符,都應注意以下幾點:

(1)確保對象沒有自我賦值(如a = a)。

(2)復用被賦值對象中的資源或銷毀它。

(3)從源對象中將待復制內容復制到目的對象。

(4)最后,返回對目的對象的引用。

賦值操作符已在類中聲明。TIntStack類的賦值操作符簽名如下:

TIntStack& operator=(TIntStack& source) // ① TIntStack& operator=(const TIntStack& source) // ②``` 下面是賦值操作符的實現:

TIntStack& TIntStack::operator=(const TIntStack& source)
{
  // 檢查自我復制(即a = a)。
  // source是被賦值的對象,&source給出對象source的地址,
  // ‘this’是被賦值對象的地址。
  if (this == &source) {
      cout << “Warning: Assignment to self.n”;
      return *this;
  }
   /*
    如果源對象棧中的元素數目小于或等于目的對象的大小,則沒有任何問題。
    我們要做的就是復制棧中相應的元素和_count變量。
    但是,如果源對象棧中元素的數目大于目的對象的大小,則必須先刪除目的對象_sp中內存,再為其分配新的內存(與源對象棧中元素的數目相等),然后復制所有元素。
   */
  if (source._count > this->_size) {
     // 源對象中元素的數目大于目的對象的大小,
     // 刪除_sp中的內存并重新分配內存。
     // 見下文解釋
      delete [] _sp;
      this->_size = source._size;
      _sp = new int [ this->_size ];
  }
    // 無論是小于等于還是大于的情況,都會用到以下代碼遍歷棧,
    // 并復制元素
    for (int i = 0; i < source._count; i++)
      this->_sp[i] = source._sp[i]; // 復制元素
    this->_count = source._count;
    return *this; // 見下文解釋
}`
分析:賦值操作由程序員顯式完成,系統(編譯器)絕不會直接調用它。賦值是在兩個現有對象之間執行的操作。如下語句:
`
a = b;`
當a和b都為對象時,上句可解析為:
`
operator=(b);`
換言之,左側(left hand side,縮寫為LHS)的對象調用成員函數operator=(),右側(right hand side,縮寫為RHS)操作數作為operator=()的參數。賦值操作右側的對象(該例中為b)不能被修改,該操作的副作用(side effect)是:返回對左側對象(該例中為a)的引用。因為不能修改右側的對象(我們只能讀取右側對象并寫入左側對象),所以該對象應作為const實參傳遞給operator=()函數(如②所示)。然而,如果使用沒有const參數的賦值操作符(如①所示),就可以被修改右側的對象。我們并不推薦使用①這樣的賦值操作符,因為類的用戶并不希望在賦值操作中改變右側的對象。由于a和b都是真正的現有對象,因此,將b賦值給a時,a中的值將被b中的值擦寫(overwrite)。

記住:

如果我們在類中未提供賦值操作符,編譯器會為類生成一個默認賦值操作符(編譯器絕不會自動調用它,但確實會生成一個)。但是,這樣的默認賦值操作符可能無法滿足我們的要求,下一章將對此作詳細介紹。

在任何賦值操作中,我們要做的就是將數據從源對象賦值到目的對象。一般而言,這很容易,但在某些情況下會有困難。在TIntStack的示例中,我們需要從源棧賦值到目的棧。如果源棧中的元素數目少于或等于目的棧中的可用空間,賦值操作便非常簡單,只需復制相應的棧元素。但是,如果源棧中的元素數目多于目的棧所能持有的數目會怎樣?我們不允許這樣的操作發生,在打印出錯誤消息后將從賦值操作返回。不過,這樣限制太大。或者,我們可以改變目的棧的大小,使其能容納所有元素。如果我們接受后者的方案,就需要在目的棧上為源棧的元素分配與源棧大小相等的新內存。這樣做之前,我們還要刪除目的棧中_sp所指向的現有內存(無法擴展這個內存),這就是上面的賦值操作符中調用delete所完成的任務。一旦完成內存分配,我們就只需要復制相應的元素進棧即可(見圖3-3和圖3-4)。

(摘自前面的main程序)

TIntStack a(5);  // 自動對象(_auto object_),在退出main時被銷毀 TIntStack b(20);  // 另一個自動對象``` 最后,我們返回對目的對象(也就是棧a)的引用。你可能會質疑,為什么要這樣做?假設我們編寫了一個級聯賦值操作(cascaded assignment operation)如下:`c = a = b; // 將b賦值給a,然后將結果再賦值給c` 賦值操作按從右到左的順序執行1,此表達式即轉換為:`c = (a = b); // 首先將b賦值給a,然后將結果賦值給c` 警告: 既然可以寫“a = b;”,那么也可以寫`a = a; // 語法上正確,但是邏輯上錯誤!` 這樣的表達式可能會通過指針和引用(別名)直接或間接地發生,我們的實現必須檢查是否出現這種情況。因此,必須核實源地址和目的地址是否相同。如果賦值發生在相同的對象之間,則不會進行任何操作,只返回對目的對象的引用。這就是上面示例的實現中,進行自我賦值檢查所完成的工作。如果沒有進行自我賦值檢查,可能會導致嚴重問題。考慮以下包含指針數據成員的TString類:

class TString {
    public:
       TString (const char* sp) {
         _data = new char[strlen(sp) + 1];
          strcpy(_data, sp);
       }
       TString & operator=(const TString & assign);
    private:
       char* _data; // 字符串指針
};
TString& TString::operator=(const TString& assign)
{
    // 錯誤代碼,未檢查自我賦值  
  delete [] this->_data; // ①
   data = new char[strlen(assign.data) + 1]; // ②
   strcpy(this->_data, assign._data);
   return *this;
}
TString x1(“Text string1”);
x1 = x1;`
以上operator=的實現并不安全,其中的①,刪除的是x1._data。接著在②中,我們又試圖使用assign._data。因為左側的對象(*this)與右側的對象(assign)是同一個對象,即assign._data與x1._data相同。所以,我們搬起石頭砸自己的腳。當執行②時,該程序可能崩潰,或者在別的地方出現問題。因此,在賦值操作的實現中,必須進行自我賦值檢查。

圖3-4

將b賦值給a非常簡單,之前的示例中已介紹過賦值如何工作。我們希望將賦值(b賦值給a)的結果再賦值給c。為使其正常工作,第1個賦值操作應返回a的值(或對a的引用)。否則,從a到c的第2次賦值就會出問題。通常,在C和C++中,我們只知道使用賦值操作的結果,卻并不了解內部的實現。例如,正是因為賦值操作的副作用,才使得以下代碼可以正常工作:

int i = 10, j = 20; // 此處無賦值操作 int k; cout << (i = j) << endl; // 將j賦值給i,并打印賦值結果①。if (k = j) { // 將j賦值給k,如果結果不為0,執行if體內部的語句②。// 省略此處代碼 }``` 在①中,完成賦值后返回i的值,并打印該值。與此類似,在②中,將j賦值給k,完成賦值后,返回k的值并與0進行比較。為了讓以上賦值都能正常工作,必須確保在賦值操作完成后,該賦值操作返回對a對象的引用。`Pascal:`在類似Pacal的語言中,以下的賦值操作沒有副作用:`a := b;` 在賦值后無法返回a的值。因此,以下語句`c := a := b;` 無法在Pascal(以及類似的語言,如Modula-2)中使用。思考:對比復制構造函數和賦值操作符中的代碼,會發現很多相似的地方。它們都將現有對象復制到另一個對象中。但是,你能否發現兩處代碼的主要差別?換言之,復制構造函數和賦值操作符的代碼有何區別?能否讓它們共享實現?為完成TIngStack的示例,其余的成員函數實現如下:

void TIntStack::Push(int what)
{
   if (_count < _size) {  // 如有更多空間儲存元素
    _sp[_count] = what;  // 儲存元素
    _count++;  // 遞增count
   }
   else {
    cout << “Stack is FULL. Cannot Push value” << what << endl;
   }
}
int TIntStack::Pop()
{
   if (_count <= 0) { // 棧為空
     cout << “Stack is EMPTYn”;
     exit (1);  // 如果失敗如何報錯?可在此處拋出異常。
   }
   _count--;
   return _sp[_count];
}
unsigned TIntStack::HowMany() const
{
   return _count;
}`
1此處用到操作符重載和操作符結合律,將在第8章中介紹。在本章討論中,只需記住賦值從右向左結合。
本文僅用于學習和交流目的,不代表異步社區觀點。非商業轉載請注明作譯者、出處,并保留本文的原始鏈接。

總結

以上是生活随笔為你收集整理的《C++面向对象高效编程(第2版)》——3.4 赋值操作符的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 秋霞欧美一区二区三区视频免费 | 婷婷在线播放 | 亚洲一区中文字幕在线观看 | 久久精品久久久久 | 国产三级全黄裸体 | 久久免费国产精品 | 久久91亚洲精品中文字幕奶水 | 国产在线123 | 极品人妻videosss人妻 | 一级黄色a视频 | 草草影院ccyycom | 精品久久国产视频 | 黄色a∨ | 97自拍视频在线 | 国产欧美一区二区三区在线看 | 久久视频免费看 | 郑艳丽三级 | 亚洲av综合av一区二区三区 | 澳门黄色录像 | 精品欧美一区二区久久久 | 国产一级二级毛片 | 美女131爽爽爽 | 国产成人无码久久久精品天美传媒 | 青草青草久热 | 亚洲精品乱码久久久久久日本蜜臀 | 精品无码久久久久成人漫画 | 永久免费无码av网站在线观看 | 男女在楼梯上高潮做啪啪 | 中日韩欧美在线观看 | 密臀av一区二区 | 日本美女视频 | 毛片在哪看 | 欧美亚洲日本在线 | 日韩国产欧美一区二区 | 日本在线播放一区 | 国产精品成久久久久三级 | 亚洲最大综合网 | 99视屏| 性感美女一级片 | 欧美日韩精品久久久 | 99视频在线精品免费观看2 | av网站地址 | 国产一区二区三区视频免费观看 | 五月天精品 | 国产精品黄网站 | 91福利在线导航 | 九九热免费 | 国产久操视频 | 91在线视频播放 | 国产精品18p| 日本黄色片视频 | 国产精品午夜未成人免费观看 | 三级黄在线观看 | 免费av软件| 最新的av网站| 波多野结衣三区 | a级黄色在线观看 | 色哟哟视频网站 | 性囗交免费视频观看 | 在线看片黄 | 黄色一级免费看 | 欧美成人三级伦在线观看 | 日韩不卡一区二区 | 欧美午夜精品久久久久久孕妇 | 免费av动漫| 亚洲天天综合 | youjizz.com中国| 国产精品成人69xxx免费视频 | 91成人综合 | 理论片高清免费理伦片 | 国产精品视频一二三区 | 久草国产视频 | 欧美性生活xxx | 公肉吊粗大爽色翁浪妇视频 | 天堂网91| 一级大黄毛片 | 97性视频 | 免费成人精品 | 99青青草| 自拍偷拍在线播放 | 一区二区一级片 | 日本中出视频 | 国产精品扒开腿做爽爽爽视频 | 国产午夜在线视频 | 麻豆免费在线播放 | 三级色网 | 久久特黄 | 女人舌吻男人茎视频 | 日本久色 | 在线免费av网站 | 秋霞啪啪片 | 国内免费毛片 | 欧美熟妇乱码在线一区 | 欧美一级久久久 | 欧美国产日韩综合 | 日本黄页网站免费大全 | 一级片在线观看视频 | 九九九在线视频 | 粉嫩av四季av绯色av |