1. 程式人生 > 其它 >OCC集合類 NCollection_Array1原始碼解析

OCC集合類 NCollection_Array1原始碼解析

// NCollection_Array1是一個模板類,容器類是模板類我們對這應該很熟悉了,畢竟為所有型別單獨寫一個容器類是不現實也沒必要的。

// 元素記憶體是順序儲存的,類似vector

// 此類中有一個顛覆我思想的操作,特此記錄。在上學、培訓時老師都教我們程式中不能有野指標,但此類正是通過“野指標”實現了任意範圍的控制。跳出固定思維很重要啊。

// 此類的範圍是閉區間 [a,b]

template <class TheItemType>

class NCollection_Array1

{

public:

    // 值型別重定義,目的不詳。原始碼註釋:和STL定義保持一致

    typedef TheItemType value_type;

public:

    // 迭代器類定義

    class Iterator

    {

    };

public:

    NCollection_Array1()

       : myLowerBound(1), myUpperBound(0), myDeletable(false), myData(nullptr)

    {}

    NCollection_Array1(const int theLower, const int theUpper)

        : myLowerBound(theLower),  myUpperBound(theUpper), myDeletable(true)

    {

        // 輸入有效性判斷,不合理拋異常。後續不再記錄常規異常處理程式碼

        Standard_RangeError_Raise_if(xxx);

        // 申請記憶體

         TheItemType *pBegin = new TheItemType[Length()];

         // 顛覆本人固有邏輯的操作。有效地址為pBegin,使myData指向無效但可控的0下標地址。

         myData = pBegin - theLower;

    }

    NCollection_Array1(const NCollection_Array1 &theOther)

        : myLowerBound(theOther.Lower()),  myUpperBound(theOther.Upper()), myDeletable(true)

    {

        TheItemType *pBegin = new TheItemType[Length()];

        myData = pBegin - myLowerBound;

        Assign(theOther);

    }

    

    // 通過現有資料(通常是C形式陣列)構造,不負責記憶體管理(myDeletable=false)

    NCollection_Array1(const TheItemType &theBegin, const int theLower, const int theUpper)

        :myLowerBound(theLower), myUpperBound(theUpper), myDeletable(false)

    {

        myData = (TheItemType *)&theBegin - theLower;

    }

    // theValue覆蓋所有現有資料

    void Init(const TheItemType &theValue)

    {

        TheItemType *pCur = &myData[myLowerBound],

                               *pEnd = &myData[myUpperBound];

        for (; pCur <= pEnd; pCur++)

              *pCur = (TheItemType &)theValue;

    }

    // 集合中元素數量查詢

    int Size() const { return Length(); }

    int Length() const { return myUpperBound - myLowerBound + 1; }

    bool IsEmpty() const { return myUpperBound < myLowerBound; }

    int Lower() const { return myLowerBound; }

    int Upper() const { return myUpperBound; }

    // 判斷資料是否需要被釋放

    bool IsDeletable() const { return myDeletable; }

    bool IsAllocated() const { return myDeletable; }

    // 拷貝theOther中資料。要求兩容器中元素個數相同

    NCollection_Array1 &Assign(const NCollection_Array1 &theOther)

    {

        if (&theOther == this) return *this;

        if (nullptr == myData)  return *this;

        TheItemType *pMyItem = &myData[myLowerBound];

        TheItemType *const pEndItem = &(theOther.myData)[theOther.myUpperBound];

        TheItemType *pItem = &(theOther.myData)[theOther.myLowerBound];

        // * 和 ++運算子優先順序

        while(pItem <= pEndItem) *pMyItem++ =  *pItem++;

        return *this;

    }

    // 把theOther記憶體中資料移動過來,移動後,theOther仍可以讀取,但是不負責資料的儲存了

    NCollection_Array1 &Move(NCollection_Array1 &theOther)

    {

        if (&theOther == this) return *this;

        if (myDeletable)  delete []&myData[myLowerBound];

        myLowerBound = theOther.myLowerBound;

        myUpperBound = theOther.myUpperBound;

        myDeletable = theOther.myDeletable;

        myData = theOther.myData;

        theOther.myDeletable = false

        return *this;

    }

    NCollection_Array1 &operator =(const NCollection_Array1 &theOther)

    {

        return Assign(theOther);

    }

    const TheItemType &First() const  { return myData[myLowerBound]; }

    TheItemType &ChangeFirst() { return myData[myLowerBound]; }

    const TheItemType &Last() const { return myData[myUpperBound]; }

    TheItemType &ChangeLast() { return myData[myUpperBound]; }

    const TheItemType &Value(const int theIndex) const { return myData[theIndex]; }

    const TheItemType &operator [](const int theIndex) const { return Value(theIndex); }

    TheItemType &ChangeValue(const int theIndex) { return myData[theIndex]; }

    TheItemType &operator ()(const int theIndex) { return ChangeValue(theIndex); }

    TheItemType &operator [](int theIndex) { return ChangeValue(theIndex); }

    

    void SetValue(int theIndex, const TheItemType &theItem) {myData[theIndex] = theItem; }

    // 重置邊界。

    // 如果新的長度和之前長度相等,則僅改變theLower, theUpper

    // 如果theToCopyData為true,則會拷貝原有的資料,拷貝的資料個數為前、後長度的較小值

    void Resize(const int theLower, const int theUpper, const bool theToCopyData)

    {

        const int anOldLen = Length();

        const int aNewLen = theUpper - theLower + 1;

        TheItemType *aBeginOld = nullptr != myData ? &myData[myLowerBound] : nullptr;

        myLowerBound = theLower;

        myUpperBound = theUpper;

        if (aNewLen == anOldLen)

         {

              myData = aBeginOld - theLower; 

              return;

         }

          if (!theToCopyData && myDeletable)  delete []aBeginOld;

        TheItemType *aBeginNew = new TheItemType[aNewLen];

        myData = aBeginNew - theLower;

        if (!theToCopyData)

        {  myDeletable = true;  return;}

        const int aLenCopy = Min(anOldLen, aNewLen);

        for (int anIter = 0; anIter < aLenCopy; ++anIter)

             aBeginNew[anIter] = aBeginOld[anIter];

    if (myDeletable) delete []aBeginOld;

    myDeletable = true;

    }

    ~NCollection_Array1()

    {

        if (myDeletable)  delete []&(myData[myLowerBound]);

    }

protected:

    int myLowerBound;

    int myUpperBound;

    bool myDeletable;

    TheItemType *myData;  // 指向下標為0的元素(可能為“野指標”)

};