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

MFC CArray 作為函數參數與回傳值的正確姿勢:避開拷貝建構陷阱

     編輯:關於VC++

MFC CArray 作為函數參數傳遞與回傳值時,若不當處理易觸發「缺少拷貝建構函數」編譯錯誤。本文系統解析三種傳遞模式、結構體嵌套應用與實戰範例。

三種參數傳遞模式對比

模式宣告範例特點適用場景
值傳遞void Func(CArray<int,int> arr)觸發拷貝建構,**需元素型別支援拷貝**,效能差極少用,除非刻意需副本
引用傳遞 (推薦)void Func(CArray<int,int>& arr)無拷貝、可修改原陣列、效能最佳輸出參數、雙向資料交換
指標傳遞void Func(CArray<int,int>* pArr)無拷貝、可為 NULL、語義明確輸出輸出參數、選擇性修改
const 引用void Func(const CArray<int,int>& arr)無拷貝、唯讀、可接臨時物件輸入參數、不修改內容

CArray 模板參數雙重含義


CArray  // Type: 回傳/儲存類型, ArgType: 輸入/傳遞類型

// 範例
CArray arr1;        // Add/GetAt 使用 double (值傳遞)
CArray arr2;       // Add/GetAt 使用 double& (引用傳遞,避免拷貝)
CArray arr3;       // 結構體建議用引用避免拷貝
CArray arr4;  // 指標陣列

結構體嵌套 CArray 實戰


struct DriverItem {
    CString strDriverName;
    CString strProductDesc;
    CString strTBLFileName;
};

struct ControlItem {
    CString strControlType;
    CArray DriverArray;  // 引用型別避免拷貝
};

完整實戰範例:點座標陣列轉換與繪圖


// 自訂雙精度點結構 (含拷貝建構/指派,滿足 CArray 需求)
struct CPointD {
    double x, y;
    CPointD() : x(0), y(0) {}
    CPointD(double dx, double dy) : x(dx), y(dy) {}
    CPointD(const CPointD& p) : x(p.x), y(p.y) {}
    CPointD& operator=(const CPointD& rhs) { x=rhs.x; y=rhs.y; return *this; }
};

typedef CArray CPointDArray;      // 值型別
typedef CArray LPointArray;          // 長整數點引用型別

class CMyView : public CView {
    CPointDArray m_points;  // 成員變數

    // 轉換函數:const 引用輸入,引用輸出
    void ConvToXYs(const CPointDArray& src, LPointArray& dest) {
        if (src.GetSize() == 0) return;
        dest.RemoveAll();
        dest.SetSize(src.GetSize());
        for (int i = 0; i < src.GetSize(); i++) {
            const CPointD& p = src[i];  // 引用存取,無拷貝
            dest[i].x = static_cast(p.x + 0.5);
            dest[i].y = static_cast(p.y + 0.5);
        }
    }

    void OnLButtonDown(UINT nFlags, CPoint point) {
        CClientDC dc(this);
        // 產生測試資料
        for (int i = 0; i < 10; i++)
            m_points.Add(CPointD(i * 3.5, i * 5.5));
        
        LPointArray longPoints;
        ConvToXYs(m_points, longPoints);
        
        // 繪製折線 (GetData() 取得內部緩衝區指標)
        dc.Polyline(longPoints.GetData(), m_points.GetSize());
        
        CString str; str.Format(_T("點數: %d"), longPoints.GetSize());
        AfxMessageBox(str);
    }

    ~CMyView() { if (m_points.GetSize()) m_points.RemoveAll(); }
};

核心避坑指南

  1. 元素型別必須實作拷貝建構函數與指派運算子 (編譯器不會為含指標/資源的類別自動生成正確版本)
  2. 優先使用引用型別作為第二模板參數:CArray 避免 Add/GetAt 拷貝
  3. 函數參數使用 const 引用輸入、引用輸出,拒絕值傳遞
  4. 回傳值情況:C++11 移動語義優化 (MFC CArray 無移動建構),建議改用 std::vector 或輸出參數模式
  5. GetData() 僅供讀取/傳遞給 API,不可長期持有指標 (重新配置會失效)

現代化建議

新專案優先考慮 std::vector:標準化、移動語義、分配器支援、算法整合。維護舊 MFC 專案時,掌握上述模式確保 CArray 安全高效使用。

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