C ++:指针指向的值发生变化

时间:2014-02-16 07:04:23

标签: c++ arrays pointers

我正在尝试编写一个表示一组整数的类。这是一项家庭作业,但对于我的生活,我无法弄清楚这个问题。

在“IntSet”类中,我有两个私有变量;一个是指向数组的指针,另一个是数组的大小。我可以创建这个类的对象,它们按预期工作。但我有一个名为“join”的函数,它返回IntSet类的一个对象。它基本上将数组连接在一起,然后使用该数组创建返回的对象。

这是我的代码:

#include <iostream>
using namespace std;

class IntSet {
        int * arrPtr;
        int arrSize;
    public:
        //Default Constructor
        IntSet() {
            int arr[0];
            arrPtr = arr;
            arrSize = 0;
        }
        //Overloaded Constructor
        IntSet(int arr[], int size) {
            arrPtr = arr;
            arrSize = size;
        }

        //Copy Constructor
        IntSet(const IntSet &i) {
            arrPtr = i.arrPtr;
            arrSize = i.arrSize;
        }

        /*
         * Returns a pointer to the first
         * element in the array
         */
        int* getArr() {
            return arrPtr;
        }

        int getSize() {
            return arrSize;
        }

        IntSet join(IntSet &setAdd) {

            //Make a new array
            int temp[arrSize + setAdd.getSize()];

            //Add the the values from the current instance's array pointer
            //to the beginning of the temp array
            for (int i = 0; i < arrSize; i++) {
                temp[i] = *(arrPtr + i);
            }

            //Add the values from the passed in object's array pointer
            //to the temp array but after the previously added values
            for (int i = 0; i < setAdd.getSize(); i++) {
                temp[i + arrSize] = *(setAdd.getArr() + i);
            }

            //Create a new instance that takes the temp array pointer and the
            //size of the temp array
            IntSet i(temp, arrSize + setAdd.getSize());

            //Showing that the instance before it passes works as expected
            cout << "In join function:" << endl;
            for (int j = 0; j < i.getSize(); j++) {
                cout << *(i.getArr() + j) << endl;
            }

            //Return the object
            return i;
        }

};

int main() {

    //Make two arrays
    int arr1[2] = {2 ,4};
    int arr2[3] = {5, 2, 7};

    //Make two objects normally
    IntSet i(arr1, 2);
    IntSet j(arr2, 3);


    //This object has an "array" that has arr1 and arr2 concatenated, essentially
    //I use the copy constructor here but the issue still occurs if I instead use
    //Inset k = i.join(j);
    IntSet k(i.join(j));

    //Shows the error. It is not the same values as it was before it was returned
    cout << "In main function:" << endl;

    for (int l = 0; l < k.getSize(); l++) {
        cout << *(k.getArr() + l) << endl;
    }

    return 0;
}

程序编译,截至目前的输出为:

In join function:
2
4
5
2
7
In main function:
10
0
-2020743083
32737
-2017308032

我不知道为什么但每次重新编译和运行时10和0总是一样的。另外,如果我打印出指针的地址而不是值(在连接函数和主函数中),我得到相同的内存地址。

对不起,如果我滥用条款,我来自java背景,所以指针等对我来说有点新鲜。如果需要澄清,请询问。

提前致谢。

2 个答案:

答案 0 :(得分:4)

int temp[arrSize + setAdd.getSize()];

这是一个本地数组,它的生命周期在函数返回后结束。

IntSet i(temp, arrSize + setAdd.getSize());

这里使用此数组构建IntSet。实际上,构造函数只是将成员指针更改为temp

的值
IntSet(int arr[], int size) {
    arrPtr = arr;
    arrSize = size;
}

因此,由于temp并因此i.arrPtr指向的对象的生命周期在离开join后结束,因此您将拥有一个野指针。稍后在main中取消引用此指针会调用未定义的行为。

您需要使用new[]动态分配数组,然后使用delete[]将其删除。你的构造函数也是如此。另请注意,如果在析构函数中使用new[]join中的delete[],则还必须确保复制构造函数实际复制数组(使用{{1创建新数组)并复制内容)。如果只是分配指针,则源和目标对象都将指向同一个数组,并且它们也会在解构时尝试删除它,再次调用未定义的行为。

但是从这个C ++开始,你也可以使用new[]来完成所有这些工作。 (或std::vector如果你真的想要一个整数集

答案 1 :(得分:0)

您的代码最快的修复方法是更改​​

int temp[arrSize + setAdd.getSize()];

进入这个

int * temp = new int[arrSize + setAdd.getSize()];

问题是你在堆栈上分配了temp,所以当join()返回时,内存是release。通过在堆上分配内存(根据修复),当join()返回时,内存不会被释放。

您的代码还有其他问题 - 取决于分配点。我认为当你考虑在堆上有内存的含义时,大多数这些都将被修复。