堆上的动态数组扩展(值消失)

时间:2014-05-18 21:27:33

标签: c++ arrays heap

所以我有一个这样的任务,我需要使用动态数组扩展而不是向量。这让我疯了,因为我过去已经成功完成了几次,而且我一直在试图弄清楚过去2天这个问题有多么糟糕。

在我的代码中,每次我的数组变满时,我都会尝试将stringsArr的大小加倍。 我的stringsArr最初是arrCapacity 4(它的最大尺寸),包含5个值。
stringsArr是我的StringSet类的私有属性。

我已经尝试过使用堆(我应该为分配执行此操作的方式)和堆栈(仅作为检查)。

printStringsArr(): 我正在使用此函数将最终的数组打印到控制台:

void StringSet::printStringsArr() {
   for (int i = 0; i < arrIndex; i++) {
      cout << i << ": " << stringsArr[i] << endl;
   }
   cout << "\n" << arrCapacity << endl;
}

堆实现(不起作用的那个):

我添加了2个for循环来显示我的stringsArr的内容,因为当我在堆上声明一个新数组时,我不明白为什么我的stringsArr的内容会像这样改变。

if (arrIndex == arrCapacity) {

    int newCapacity = (arrCapacity * 2);

    /* Display content of stringsArr 
     before tmpArray declaration*/
    for (int i = 0; i < arrIndex; i++) {
        cout << "." << stringsArr[i] << endl;
    }
    cout <<  "\n" << endl;


    // Allocate on the heap the new empty array
    string *tmpArr = new string[newCapacity];


    /* Display te content of stringsArr after declaring 
     tmpArr on the heap*/
    for (int i = 0; i < arrIndex; i++) {
        cout << "." << stringsArr[i] << endl;
    }

    // Copy everything
    for (int i = 0; i < arrCapacity; i++) {
        tmpArr[i] = stringsArr[i];
    }

    // Update arrCapacity to its new value.
    arrCapacity = newCapacity;

    delete [] stringsArr;

    stringsArr = tmpArr;
}

堆实现输出:

// From the 1st for loop.
.Dog  
.Cat  
.Turtle  
.Lion

// For the 2nd for loop,
// mysteriously, only the first value is left.
.Dog  
.  
.  
.  

// And for the "printStringsArr()" function.
0: Dog
1: 
2: 
3: 
4: Fish

我确信我完全错过了一些东西,但我根本不知道它是什么......

堆栈实施:

if (arrIndex == arrCapacity) {

    int newCapacity = (arrCapacity * 2);

    for (int i = 0; i < arrIndex; i++) {
        cout << "." << stringsArr[i] << endl;
    }
    cout <<  "\n" << endl;


    string *tmpArr[newCapacity];


    for (int i = 0; i < arrIndex; i++) {
        cout << "." << stringsArr[i] << endl;
    }

    // Copy everything
    for (int i = 0; i < arrCapacity; i++) {
        tmpArr[i] = &stringsArr[i];
    }

    arrCapacity = newCapacity;

    delete [] stringsArr;

    stringsArr = *tmpArr;
}

堆栈实施输出:

// From the 1st for loop.  
.Dog  
.Cat  
.Turtle  
.Lion  

// For the 2nd for loop.  
.Dog    
.Cat  
.Turtle  
.Lion  

// And for the "printStringsArr()" function.  
0: Dog  
1: Cat  
2: Turtle  
3: Lion  
4: Fish  

我的大问题是&#34;为什么在我在堆上声明一个新的空数组后,我的stringsArr值会消失?&#34;。
对我来说,到目前为止,这是黑魔法,我想了解为什么会发生这种情况以及如何解决它。

感谢您的帮助。

编辑:单个文件缩写代码

#include <iostream>

using namespace std;

int main()
{
class StringSet {
public:
    StringSet() {
        this->arrCapacity = 4;
        this->arrIndex = 0;
    }

    bool insert(string str) {

        // If string already present, return false.
        for (int i =0; i < arrCapacity; i++) {
            if (stringsArr[i] == str) {
                return false;
            }
        }

        // Otherwise, insert the string at the next available index in our array.
        // If the arrCapacity is less or equal to the next index, increase the array
        // size two-folds.
        // arrIndex always point to the top empty cell of the array.

        // arrIndex points to the next free cell on the array
        if (arrIndex == arrCapacity) {

            int newCapacity = (arrCapacity * 2);

            /* Display content of stringsArr
             before tmpArray declaration*/
            for (int i = 0; i < arrIndex; i++) {
                cout << "." << stringsArr[i] << endl;
            }
            cout <<  "\n" << endl;


            // Allocate on the heap the new empty array
            string *tmpArr = new string[newCapacity];


            /* Display te content of stringsArr after declaring
             tmpArr on the heap*/
            for (int i = 0; i < arrIndex; i++) {
                cout << "." << stringsArr[i] << endl;
            }

            // Copy everything
            for (int i = 0; i < arrCapacity; i++) {
                tmpArr[i] = stringsArr[i];
            }

            // Update arrCapacity to its new value.
            arrCapacity = newCapacity;

            delete [] stringsArr;

            stringsArr = tmpArr;
        }

        stringsArr[arrIndex] = str;


        arrIndex++;

        return true;
    }


    //Dump the content of stringsArr to the console.
    void printStringsArr() {

        for (int i = 0; i < arrIndex; i++) {
            cout << i << ": " << stringsArr[i] << endl;
        }
        cout << "\n" << arrCapacity << endl;
    }

private:
    //ArrIndex shows where the index is at. If it become equal to ArrCapacity (index 2   corresponds to capacity 3, not 2),
    // the array needs to be increased in size.
    int arrIndex;
    int arrCapacity = 0;

    string *stringsArr = new string[arrCapacity];


};


StringSet* objectString = new StringSet;

objectString->insert("Dog");
objectString->insert("Cat");
objectString->insert("Turtle");
objectString->insert("Lion");
objectString->insert("Fish");
objectString->insert("Zebra");
objectString->insert("Human");
objectString->insert("Squirrel");

cout << "\n" << endl;
objectString->printStringsArr();

return 0;
}

1 个答案:

答案 0 :(得分:1)

stringsArr的初始化移动到构造函数体:

StringSet() {
    arrCapacity = 4;
    arrIndex = 0;
    stringsArr = new string[arrCapacity];
}
...
string *stringsArr;

如果没有此更改stringsArr已初始化为new string[0],稍后您的代码会对索引0,1,2和3进行数据索引溢出,从而覆盖堆的其他部分。

更好的是,只要初始化顺序与声明顺序相同:

StringSet(): arrIndex(0), arrCapacity(4), stringsArr(new string[arrCapacity]) {}

也不要在构造函数之外初始化arrCapacityarrIndex