C++學(xué)習(xí)筆記三

類(lèi)和動(dòng)態(tài)內(nèi)存分配

1. 動(dòng)態(tài)內(nèi)存和類(lèi)

靜態(tài)成員

  • 注意: 靜態(tài)數(shù)據(jù)成員在類(lèi)中聲明,在類(lèi)外初始化, 但如果靜態(tài)成員是const整數(shù)類(lèi)型或枚舉型可以在類(lèi)聲明中初始化
  • 靜態(tài)成員初始化時(shí)不加static限定符, 否則會(huì)將其作用域局限在所在的文件

new和delete

  • 構(gòu)造函數(shù)使用new分配內(nèi)存時(shí), 必須在相應(yīng)的析構(gòu)函數(shù)中delete來(lái)釋放, 如果使用new [ ]來(lái)分配內(nèi)存,則應(yīng)使用delete [ ]來(lái)釋放
  • 如果有多個(gè)構(gòu)造函數(shù), 則必須以相同的方式使用new, 要么都帶中括號(hào), 要么都不帶

特殊成員函數(shù)

  • C++自動(dòng)提供以下函數(shù):
  • 默認(rèn)構(gòu)造函數(shù), 如果沒(méi)有定義任何構(gòu)造函數(shù)
  • 默認(rèn)析構(gòu)函數(shù), 如果沒(méi)有定義
  • 默認(rèn)拷貝構(gòu)造函數(shù), 如果沒(méi)有定義
  • 賦值運(yùn)算符重載, 如果沒(méi)有定義
  • 地址運(yùn)算符重載, 如果沒(méi)有定義
  • C++11 還提供了移動(dòng)構(gòu)造函數(shù)和移動(dòng)賦值函數(shù)
  • 警告: 當(dāng)類(lèi)中包含了使用new初始化的指針成員, 應(yīng)當(dāng)定義一個(gè)拷貝構(gòu)造函數(shù), 用來(lái)復(fù)制數(shù)據(jù)而不是簡(jiǎn)單的指針復(fù)制.
  • 賦值運(yùn)算符

C++允許類(lèi)對(duì)象賦值, 就是通過(guò)自動(dòng)為類(lèi)重載賦值運(yùn)算符實(shí)現(xiàn)的
將已有的對(duì)象賦給另一個(gè)對(duì)象時(shí), 將使用重載的賦值運(yùn)算符
使用已有對(duì)象初始化另一對(duì)象時(shí), 可能會(huì)使用賦值運(yùn)算符

2. String類(lèi)

  • 函數(shù)成員使用new動(dòng)態(tài)分配, 應(yīng)提供拷貝構(gòu)造函數(shù)和重載賦值運(yùn)算
  • String類(lèi)簡(jiǎn)單實(shí)現(xiàn)代碼:
/*
 * String.h
 */
#ifndef CPLUSPLUS_STRING_H
#define CPLUSPLUS_STRING_H

#include <iostream>
#include <cstring>
using namespace std;
class String {
public:
    String();                // 默認(rèn)構(gòu)造函數(shù)
    String(const char* str); // 普通構(gòu)造函數(shù)
    String(const String& s); // 拷貝構(gòu)造函數(shù)
    ~String();               // 析構(gòu)函數(shù)
    String &operator=(const String& s); // 重載賦值運(yùn)算
    String &operator=(const char* str); // 重載賦值運(yùn)算
    friend ostream &operator<<(ostream& os, const String& s);
private:
    char* m_str;
    size_t length;
};
#endif //CPLUSPLUS_STRING_H

/*
 * String.cpp
 */
#include "String.h"
String::String(const char* str) {
    length = std::strlen(str);
    m_str = new char[length + 1];
    strcpy(m_str, str);
}

String::String() {
    length = 0;
    m_str = nullptr;
}

String::String(const String& s) {
    length = s.length;
    m_str = new char[length + 1];
    strcpy(m_str, s.m_str);
}

String::~String() {
    delete [] m_str;
    m_str = nullptr;
}

String &String::operator=(const String &s) {
    if (this == &s) { // 檢查是否為自身賦值
        return *this;
    }
    delete [] m_str;
    length = s.length;
    m_str = new char[length + 1];
    strcpy(m_str, s.m_str);
    return *this;
}

String &String::operator=(const char *str) {
    delete [] m_str;
    length = strlen(str);
    m_str = new char[length + 1];
    strcpy(m_str, str);
    return *this;
}

ostream &operator<<(ostream &os, const String &s) {
    os << s.m_str;
    return os;
}
  • C++11 提供了關(guān)鍵字nullptr來(lái)表示空指針, 盡量使用nullptr而不是0或者NULL
  • 包含類(lèi)成員的類(lèi)的賦值或拷貝時(shí)會(huì)調(diào)用類(lèi)成員自身的賦值運(yùn)算或拷貝構(gòu)造函數(shù)

3. 定位new運(yùn)算符

  • 定位new運(yùn)算符用于為類(lèi)對(duì)象分配空間時(shí),需要顯式調(diào)用類(lèi)的析構(gòu)函數(shù)(如果需要析構(gòu)的話(huà))
char *buffer = new char[1024];
String* pn = new (buffer) String;

pn->~String();      // 顯示調(diào)用析構(gòu)函數(shù)
delete [] buffer;   // 釋放new的空間

// 直接使用對(duì)象指針釋放是錯(cuò)誤的
delete pn;          // 錯(cuò)誤, 不能釋放buffer且不會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù)

4. 成員初始化列表

  • 只能用于構(gòu)造函數(shù)
  • 必須用這種格式來(lái)初始化非靜態(tài)const類(lèi)型數(shù)據(jù)成員
  • 必須用這種方法來(lái)初始化引用數(shù)據(jù)成員
  • 數(shù)據(jù)成員初始化的順序與初始化器中的順序無(wú)關(guān), 和成員的聲明順序一致
  • C++11 允許直接在類(lèi)內(nèi)聲明時(shí)初始化成員
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容