91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++構造函數常見的坑有哪些

發布時間:2022-01-04 00:23:55 來源:億速云 閱讀:105 作者:柒染 欄目:開發技術

今天就跟大家聊聊有關C++構造函數常見的坑有哪些,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

某一天我們接到了一個需求,需要開發一個類似于STLstring的類。

我們很快寫好了代碼:

#include <iostream>
#ifndef STRINGBAD_H_
#define STRINGBAD_H_
class StringBad {
    private:
     char *str;
     int len;
     static int num_strings;
    public:
     StringBad(const char* s);
     StringBad();
     ~StringBad();
     friend std::ostream & operator << (std::ostream &os, const StringBad & st);
};
#endif

在這個.h文件當中,我們定義了一個StringBad類,這是C++ Primer當中的一個例子。為什么叫StringBad呢,主要是為了提示,表示這是一個沒有完全開發好的demo

這里有一個小細節,我們在類當中定義的是一個char *也就是字符型指針,而非字符型數組。這意味著我們在類聲明當中沒有為字符串本身分配空間,而是在構造函數當中使用new來完成的,避免了預先定義字符串的長度。

其次num_strings是一個靜態成員,也就是說無論創建了多少對象,它都只會保存一份。類的所有成員共享同一個靜態變量。

接下來我們來看一下它的實現:

#include <cstring>
#include "stringbad.h"

using std::cout;

int StringBad::num_strings = 0;

StringBad::StringBad(const char* s) {
    len = std::strlen(s);
    str = new char[len+1];
    std::strcpy(str, s);
    num_strings++;
    cout << num_strings << ": \"" << str << "\" object created \n";
}

StringBad::StringBad() {
    len = 4;
    str = new char[4];
    std::strcpy(str, "C++");
    num_strings++;
    cout << num_strings << ": \"" << str << "\" object created \n";
}

StringBad::~StringBad() {
    cout << "\"" << str << "\" object deleted, ";
    --num_strings;
    cout << num_strings << " left \n";
    delete []str;
}

std::ostream & operator<<(std::ostream & os, const StringBad &st) {
    os << st.str;
    return os;
}

首先,我們可以注意到第一句就是將num_strings初始化成了0,我們不能在類聲明中初始化靜態成員變量。因為聲明只是描述了如何分配內存,但并不真的分配內存。

所以對于靜態類成員,我們可以在類聲明之外使用單獨的語句進行初始化。因為靜態成員變量是單獨存儲的,并不是對象的一部分。

初始化要在方法文件也就是cpp文件當中,而不是頭文件中。因為頭文件可能會被引入多次,如果在頭文件中初始化將會引起錯誤。當然也有一種例外,就是加上了const關鍵字。

從邏輯上看,我們這樣實現并沒有任何問題,但是當我們執行的時候,就會發現問題很多&hellip;&hellip;

假設我們現在有一個函數:

void callme(StringBad sb) {
 cout << "    \"" << sb << "\"\n";
}

然后我們這么使用:

int main() {
 StringBad sb("test");
 callme(sb);
 return 0;
}

會得到一個奇怪的結果:

C++構造函數常見的坑有哪些

從屏幕可以看到我們的析構函數執行了兩次,一次很好理解應該是main函數退出的時候自動執行的,還有一次呢?是什么時候執行的?

答案是執行callme函數的時候執行的,因為callme函數使用了值傳遞。當callme函數執行結束時,也會調用參數sb的析構函數。

如果我們改成引用傳遞,就一切正常了:

void callme(StringBad &sb) {
 cout << "    \"" << sb << "\"\n";
}

int main() {
 StringBad sb("test");
 callme(sb);
 return 0;
}

C++構造函數常見的坑有哪些

這還沒完,我們把代碼再改一下,會發現還有問題:

int main() {
 StringBad sb("test");
 StringBad sports("Spinach Leaves Bowl for Dollars");
 StringBad sailor = sports;
 StringBad knot;
 StringBad st = sb;
 return 0;
}

執行一下,得到:

C++構造函數常見的坑有哪些

會發現又有負數出現了,這是為什么呢?

因為我們執行了StringBad st = sb這樣的操作,這個操作并不會調用我們實現的任何一個構造函數。

它等價于:

StringBad st = StringBad(sb);

對應的構造函數原型是:

StringBad(const StringBad&);

當我們用一個對象來初始化另外一個對象的時候,編譯器將會自動生成上述的構造函數。這樣的構造函數叫做拷貝構造函數,由于我們沒有重載拷貝構造函數,因此它不知道要對num_strings變量做處理,也就導致了不一致的發生。

看完上述內容,你們對C++構造函數常見的坑有哪些有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

南陵县| 天柱县| 浦江县| 普定县| 色达县| 清新县| 鹤壁市| 读书| 迭部县| 松潘县| 利辛县| 杭锦后旗| 宾阳县| 吴堡县| 林口县| 南阳市| 秦安县| 赞皇县| 佳木斯市| 永昌县| 虹口区| 洞口县| 长寿区| 若尔盖县| 乐都县| 广元市| 通江县| 邛崃市| 泰和县| 凤阳县| 庄河市| 杭锦后旗| 周至县| 长泰县| 邢台县| 威远县| 连江县| 甘谷县| 辽源市| 辉县市| 聂荣县|