首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

BCB 動態建立控制項陣列:雙重指標 vs TList 兩大方案深度對比

     編輯:VC 教學

問題背景

動態建立一組按鈕(或其他控制項),常見做法用 TList 存指標,但釋放時 TList::Clear() 僅清空指標陣列,**不會 delete 物件**,導致記憶體洩漏。本文對比兩種正確釋放方案。

方案一:雙重指標陣列—— 純 C++ 風格,高效彈性

建立

// 表單成員
TButton** Buttons = nullptr;
int BtnCount = 0;

void __fastcall TForm1::CreateButtons(int count) {
    Buttons = new TButton*[count];        // 1. 分配指標陣列
    for (int i = 0; i < count; ++i) {
        Buttons[i] = new TButton(this);   // 2. 逐個建立控制項
        Buttons[i]->Parent = this;
        Buttons[i]->SetBounds(10, 10 + i*30, 90, 25);
        Buttons[i]->Caption = "Btn " + IntToStr(i);
    }
    BtnCount = count;
}

釋放

void __fastcall TForm1::FreeButtons() {
    for (int i = 0; i < BtnCount; ++i)
        delete Buttons[i];                // 1. 刪除每個控制項
    delete[] Buttons;                     // 2. 刪除指標陣列
    Buttons = nullptr;
    BtnCount = 0;
}

方案二:TList 容器—— VCL 風格,功能豐富

建立


TList* Buttons = new TList();

void __fastcall TForm1::CreateButtons(int count) {
    for (int i = 0; i < count; ++i) {
        TButton* btn = new TButton(this);
        btn->Parent = this;
        btn->SetBounds(10, 10 + i*30, 90, 25);
        btn->Caption = "Btn " + IntToStr(i);
        Buttons->Add(btn);
    }
}

釋放(關鍵:強制轉型後 delete)

void __fastcall TForm1::FreeButtons() {
    for (int i = 0; i < Buttons->Count; ++i) {
        TButton* btn = static_cast(Buttons->Items[i]);
        delete btn;                       // 必須顯式 delete
    }
    Buttons->Clear();                     // 清空指標陣列
    delete Buttons;                       // 刪除 TList 本身
    Buttons = nullptr;
}

原理:TList::Items 為 void*,需 static_cast 才能呼叫解構函數。也可轉 TControl* 或 TComponent*(VCL 根基類)。

深度對比

維度雙重指標TList
效能極高(連續記憶體、無額外開銷)稍低(動態擴容、介面呼叫)
記憶體佔用最小略大(內部緩衝區)
功能豐富度僅索引存取排序、搜尋、插入、刪除、迭代器
程式碼複雜度需手動管理兩層 new/delete語意清晰、符合 VCL 慣用模式
型別安全編譯期保證執行期轉型,需開發者保證型別正確
擴充性固定大小,擴容需手動 realloc動態增減,自動擴容

現代 C++Builder 最佳實踐

C++11 以降,優先使用標準容器 + 智慧指標:

#include 
#include 

std::vector> Buttons;

void CreateButtons(int count) {
    Buttons.reserve(count);
    for (int i = 0; i < count; ++i) {
        auto btn = std::make_unique(this);
        btn->Parent = this;
        btn->SetBounds(10, 10 + i*30, 90, 25);
        btn->Caption = "Btn " + IntToStr(i);
        Buttons.push_back(std::move(btn));
    }
}
// 無需手動釋放,vector 析構自動釋放 unique_ptr,進而 delete TButton

優點:零記憶體洩漏、異常安全、語法簡潔、標準化。舊專案逐步遷移即可。

總結

  • 傳統專案:雙重指標求極致效能,TList求開發效率與 VCL 一致性。
  • 現代專案:std::vector + std::unique_ptr 一統江湖。
  • 核心鐵律:每個 new 必須配對 delete,Owner 機制不適用於非視覺樹物件。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved