首页 > 解决方案 > 数组索引重载错误

问题描述

为什么这段代码会导致数组的第二个元素被打印为 0,而不管整数数组对象的定义中指定的值是什么?下面代码的输出是 7 0 3 4 5 6 而不是 7 2 3 4 5 6,这种行为的原因是什么?

// Overloading operators for Array class
#include<iostream>
#include<cstdlib>

using namespace std;

// A class to represent an integer array
class Array
{
private:
    int *ptr;
    int size;
public:
    Array(int *, int);

    // Overloading [] operator to access elements in array style
    int &operator[] (int);

    // Utility function to print contents
    void print() const;
};

// Implementation of [] operator.  This function must return a
// reference as array element can be put on left side
int &Array::operator[](int index)
{
    if (index >= size)
    {
        cout << "Array index out of bound, exiting";
        exit(0);
    }
    return ptr[index];
}

// constructor for array class
Array::Array(int *p = NULL, int s = 0)
{
    size = s;
    ptr = NULL;
    if (s != 0)
    {
        ptr = new int[s];
        for (int i = 0; i < s; i++)
            ptr[i] = p[i];
        delete ptr;
    }
}

void Array::print() const
{
    for(int i = 0; i < size; i++)
        cout<<ptr[i]<<" ";
    cout<<endl;
}

// Driver program to test above methods
int main()
{
    int a[] = {1, 2, 3, 4, 5, 6};
    Array arr1(a, 6);
    arr1[0] = 7;
    arr1.print();
    arr1[8] = 6;
    return 0;
}

标签: c++arraysoperator-overloadingoverloading

解决方案


Array构造函数中,在分配和填充动态分配ptr的缓冲区后立即释放缓冲区

delete ptr;

在此之后对缓冲区的所有访问都会ptr调用未定义的行为。旁注:这应该是delete[] ptr;为了确保正确释放阵列。

解决方案:不要那样做!

ptrArray超出范围并使用缓冲区完成时,添加一个析构函数以释放。

// destructor for array class
Array::~Array()
{
    delete[] ptr;
}

delete[]编译器会自动为您生成一个析构函数,但该泛型析构函数没有资格知道它对指针成员的内容是否安全。它可能不是一个数组,分配可能由另一个对象拥有(参见什么是资源或指针的所有权?)或者可能不是动态分配的new

这带来了一个旁注:处理复制此对象的默认特殊成员函数将盲目地复制指针,而不是分配,并留下两个指向同一分配的对象。迟早这将是致命的,因为一个副本将在另一个之前超出范围,如果没有其他尝试访问释放的分配并破坏程序,第二个delete[]将破坏程序。什么是三法则

一般的经验法则是不要创建这样的类,而是使用std::vector. std::vector完成所有这些以及更多。


推荐阅读