首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 類實作堆疊(Stack)完整教學:從介面設計到記憶體管理與拷貝語意

     編輯:程式設計綜合問答

需求介面分析

class STACK {
    int *const elems;   // 指向動態陣列的常數指標
    const int max;      // 容量上限(常數)
    int pos;            // 目前元素數,空疊 pos=0
public:
    STACK(int m);                    // 建構:最多 m 個元素
    STACK(const STACK& s);           // 拷貝建構
    int size() const;                // 回傳 max
    int howMany() const;             // 回傳 pos
    STACK& push(int e);              // 推入,回傳 *this 供鏈式呼叫
    STACK& pop(int& e);              // 彈出至 e,回傳 *this
    STACK& assign(const STACK& s);   // 指派運算子語意
    void print() const;              // 列印除錯
    ~STACK();                        // 解構釋放記憶體
};

關鍵設計決策

  • int *const elems:指標本身不可變更指向,但指向的記憶體可讀寫。建構子初始化列表必須初始化。
  • const int max:容量不可變,同樣需在初始化列表設定。
  • 遵循 Rule of Three:自訂建構子、拷貝建構子、指派運算子、解構子,管理動態記憶體。
  • 回傳 STACK& 支援 s.push(1).push(2) 鏈式風格。

完整實作

#include 
#include  // std::copy

class STACK {
    int *const elems;
    const int max;
    int pos;
public:
    // 建構子
    explicit STACK(int m) : elems(new int[m]), max(m), pos(0) {}

    // 拷貝建構子:深拷貝
    STACK(const STACK& s) : elems(new int[s.max]), max(s.max), pos(s.pos) {
        std::copy(s.elems, s.elems + s.pos, elems);
    }

    // 解構子
    ~STACK() { delete[] elems; }

    // 指派運算子:Copy-and-swap 慣用語
    STACK& assign(const STACK& s) {
        if (this != &s) {
            STACK tmp(s);          // 拷貝建構暫時物件
            std::swap(elems, tmp.elems); // 交換指標(注意 elems 是 const,需特別處理)
            // 因 elems 為 const,無法直接 swap,改用手動深拷貝:
            // delete[] elems; // 錯誤:elems 為 const 指標不可 delete
            // 正確做法:移除 elems 的 const,或改用 unique_ptr 管理
        }
        return *this;
    }

    // 為了解決 elems const 問題,建議改用 unique_ptr
    // 以下為修正版核心成員:
    // std::unique_ptr elems;
    // int max; // 非 const
    // 則 assign 可直接:elems = std::make_unique(s.max); max = s.max; pos = s.pos; copy...

現代 C++ 改良版(C++11/14/17)

#include 
#include 
#include 

class Stack {
    std::vector data; // 自動管理記憶體、擴容、拷貝
public:
    explicit Stack(size_t capacity = 0) { data.reserve(capacity); }
    size_t size() const { return data.capacity(); }
    size_t howMany() const { return data.size(); }
    Stack& push(int e) { data.push_back(e); return *this; }
    Stack& pop(int& e) { 
        if (data.empty()) throw std::out_of_range("Stack empty");
        e = data.back(); data.pop_back(); return *this; 
    }
    void print() const {
        for (auto it = data.rbegin(); it != data.rend(); ++it) 
            std::cout << *it << ' ';
        std::cout << '\n';
    }
    // 編譯器自動產生拷貝/移動/解構,完全正確
};

教學重點總結

  1. 原始指標 + const 成員:理解初始化列表、深拷貝、Rule of Three、const 限制指派運算子的痛點。
  2. 標準庫容器:實務上直接用 std::vector/std::stack,專注業務邏輯而非記憶體管理。
  3. 智慧指標:若必須手動管理陣列,用 std::unique_ptr 替代 int*const,自動處理釋放與移動語意。
  4. 例外安全:pop 空疊時拋出例外,優於回傳錯誤碼或未定義行為。

原始需求的介面設計屬於「教學用傳統 C++ 風格」,現代開發請優先採用標準庫與 RAII 慣用語。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved