天天看點

《More Effective C++》程式代碼詳解 第五階段

作者:明政面朝大海春暖花開

在C++中,可以通過以下幾種方式要求或禁止對象在堆(heap)中建立:

  1. 使用棧對象:在函數内部或作用域内直接聲明對象,對象将在離開作用域時自動銷毀。這是C++中常見的對象建立方式,也是最常用的方式。
  2. void func() { MyClass obj; // 在棧中建立對象 // ... }
  3. 使用靜态對象:靜态對象在程式的整個生命周期記憶體在,不會自動銷毀,可以在全局作用域或類的靜态成員中聲明。
  4. class MyClass { public: static MyClass& getInstance() { static MyClass instance; // 在靜态存儲區中建立對象 return instance; } }; int main() { MyClass& obj = MyClass::getInstance(); // 擷取靜态對象的引用 // ... return 0; }
  5. 使用智能指針:智能指針是C++中管理動态配置設定對象的一種方式,可以自動釋放對象的記憶體。可以使用shared_ptr、unique_ptr或weak_ptr等智能指針來管理堆上的對象。
  6. #include <memory> void func() { std::shared_ptr<MyClass> obj = std::make_shared<MyClass>(); // 在堆中建立對象 // ... }

需要注意的是,禁止對象在堆中建立并不是C++語言的限制,而是一種程式設計約定或最佳實踐。在實際應用中,根據具體情況選擇适當的對象建立方式,以確定記憶體的正确管理和使用。

在C++中,可以使用靜态成員變量和靜态成員函數來限制某個類所能産生的對象數量。以下是一個示例:

#include <iostream>

class LimitedClass {
private:
    static int count; // 靜态成員變量,用于記錄對象數量
    static const int maxCount = 5; // 最大對象數量限制

public:
    LimitedClass() {
        if (count >= maxCount) {
            std::cout << "已達到最大對象數量限制,無法建立更多對象。" << std::endl;
            throw std::exception();
        }
        count++;
    }

    ~LimitedClass() {
        count--;
    }

    static int getCount() {
        return count;
    }
};

int LimitedClass::count = 0;

int main() {
    try {
        LimitedClass obj1;
        LimitedClass obj2;
        LimitedClass obj3;
        LimitedClass obj4;
        LimitedClass obj5;
        LimitedClass obj6; // 超過最大對象數量限制,會抛出異常
    }
    catch (std::exception& e) {
        std::cout << "捕獲到異常:" << e.what() << std::endl;
    }

    std::cout << "目前對象數量:" << LimitedClass::getCount() << std::endl;

    return 0;
}
           

在上面的示例中,LimitedClass類中使用了一個靜态成員變量count來記錄對象數量,以及一個靜态成員變量maxCount來表示最大對象數量限制。在構造函數中,如果目前對象數量已經達到最大限制,就抛出一個異常。在析構函數中,每次對象被銷毀時,對象數量減一。我們可以通過調用靜态成員函數getCount()來擷取目前的對象數量。

在main()函數中,我們建立了5個LimitedClass對象,然後嘗試建立第6個對象,由于超過了最大限制,會抛出異常。最後,我們列印出目前的對象數量。

請注意,上述代碼隻是一個示例,用于示範如何限制類所能産生的對象數量。實際應用中,你可能需要根據具體需求進行适當的修改。

這段代碼是一個類的靜态成員變量的定義和初始化。在C++中,靜态成員變量是類的所有對象共享的變量,而不是每個對象獨有的。這意味着無論建立了多少個類的對象,靜态成員變量隻有一個副本。

在這段代碼中,`count` 是 `LimitedClass` 類的靜态成員變量,它的類型是 `int`。通過 `int LimitedClass::count = 0;` 這行代碼,将 `count` 初始化為 0。

靜态成員變量可以在類的定義外進行初始化,這樣可以確定靜态成員變量隻有一個副本,并且在使用之前已經被正确地初始化。在這個例子中,靜态成員變量 `count` 被初始化為 0,表示初始時沒有 `LimitedClass` 的對象被建立。

可以通過 `LimitedClass::count` 來通路和修改這個靜态成員變量。例如,可以使用 `LimitedClass::count++` 來對 `count` 進行自增操作。

請注意,靜态成員變量的生命周期與程式的運作周期相同,它們在程式開始運作時被建立,在程式結束時被銷毀。

當我們在C++中使用函數重載(overload)技術時,可以通過定義多個重載函數來避免隐式類型轉換(implicit type conversions)。下面是一個簡單的例子:

#include <iostream>

void printNumber(int num) {
    std::cout << "Integer number: " << num << std::endl;
}

void printNumber(double num) {
    std::cout << "Double number: " << num << std::endl;
}

int main() {
    int num1 = 10;
    double num2 = 3.14;

    printNumber(num1);   // 調用printNumber(int num)函數
    printNumber(num2);   // 調用printNumber(double num)函數

    return 0;
}
           

在這個例子中,我們定義了兩個重載函數printNumber,一個接受int類型的參數,另一個接受double類型的參數。當我們調用printNumber函數時,編譯器會根據參數的類型選擇合适的函數進行調用。這樣,我們就可以避免隐式類型轉換,確定參數的類型與函數的期望類型一緻。

在上述例子中,如果我們沒有使用重載函數,而是定義一個隻接受int類型參數的函數,那麼當我們傳遞一個double類型的參數時,編譯器會進行隐式類型轉換,将double類型轉換為int類型。使用重載函數可以避免這種不必要的類型轉換,提高代碼的可讀性和準确性。

在C++中,臨時對象是指在表達式求值過程中臨時建立的對象,它們沒有被明确命名,通常用于執行某些臨時計算或傳遞給函數。

以下是一個使用臨時對象的示例:

#include <iostream>

class MyClass {
public:
  MyClass() {
    std::cout << "Constructor called!" << std::endl;
  }

  ~MyClass() {
    std::cout << "Destructor called!" << std::endl;
  }
};

void func(MyClass obj) {
  std::cout << "Inside func()" << std::endl;
}

int main() {
  func(MyClass()); // 建立一個臨時對象并傳遞給函數func

  return 0;
}
           

在上面的示例中,MyClass是一個簡單的類,它有一個構造函數和一個析構函數。在main函數中,我們調用了func函數,并将一個臨時建立的MyClass對象作為參數傳遞給它。這個臨時對象在函數調用結束後會被銷毀,是以在輸出中可以看到構造函數和析構函數的調用順序。

請注意,臨時對象的生命周期非常短暫,它們隻在需要時被建立,并在使用完畢後立即銷毀。臨時對象的建立和銷毀是由編譯器自動處理的,無需顯式地進行管理。

繼續閱讀