【问题标题】:Overloaded Operator '=' using arrays gives a runtime error C++使用数组重载运算符“=”会导致运行时错误 C++
【发布时间】:2020-06-09 19:12:29
【问题描述】:

我正在尝试为自定义 Array 类设置重载运算符“=”以进行练习,但它似乎会导致运行时错误。

class Array {
    private:
        static int numberOfElements; //class static variable
        int size;
        int* numbers;

    public:
        Array(int);
        Array(const Array&);
        ~Array();

        int getSize();
        static int getNumberOfElements();

        Array& operator =(const Array&);
};

这个重载的运算符函数会产生正确的输出,但会出现运行时错误:

Array& Array::operator =(const Array& newArray) {
    numberOfElements = numberOfElements - size + newArray.size;
    size = newArray.size;
    for (int i = 0; i < size; i++)
        numbers[i] = newArray.numbers[i];
    return *this;
}

以前,我有

Array& Array::operator =(const Array& newArray) {
    delete[] numbers;
    numberOfElements = numberOfElements - size + newArray.size;
    size = newArray.size;
    numbers = new int[size];
    for (int i = 0; i < size; i++)
        numbers[i] = newArray.numbers[i];
    return *this;
}

这不会产生运行时,但会创建一个充满垃圾的数组。 numberOfElements 只是跟踪所有数组中的总元素,不应成为错误的一个因素。我确定问题是动态分配,但我似乎无法从逻辑上弄清楚为什么如果我只用 newArray 覆盖原始数组,为什么它会抛出运行时,以及为什么后者填充垃圾,即使分配的数组被设置为 newArray 的元素。

【问题讨论】:

  • 可能不相关,但请确保使用 .size() 而不是 .size 调用 size。
  • 第一个版本(没有 new/delete)显然是不正确的,因为新的大小可能与旧的大小不同,所以有时你写的越界
  • 第二个版本更好(虽然它应该检查自赋值并且不是异常安全的);如果它似乎不起作用,那么您可能在程序的其他地方有一个错误(这可能是一个自分配调用)。我建议使用第二个版本,如果您仍然遇到问题,请发布stackoverflow.com/help/minimal-reproducible-example
  • 如果你的复制构造函数工作正常,而你的析构函数工作正常,那么赋值运算符就变成了使用copy / swap的3行代码。请出示您的复制构造函数。
  • 为什么numberOfElements 是静态的?那是一整套自己的错误

标签: c++ arrays operator-overloading overloading dynamic-memory-allocation


【解决方案1】:

如果newArray.size 大于this-&gt;size,您的operator= 会破坏内存。它需要重新分配其numbers[] 数组以解决您最初所做的更大的大小(只是不是以异常安全的方式)。

如果newArray.size 不大于this-&gt;size,则不需要重新分配,只需将newArray.numbers 中的值原样复制到this-&gt;numbers,确保不超过newArray.size 或@987654331 中的较小者@。

试试这样的:

Array& Array::operator=(const Array& newArray)
{
    if (&newArray != this)
    {
        if (size != newArray.size)
        {
            numberOfElements -= size;

            delete[] numbers;
            numbers = NULL;
            size = 0;

            numbers = new int[newArray.size];
            size = newArray.size;

            numberOfElements += size;
        }

        for (int i = 0; i < size; ++i)
            numbers[i] = newArray.numbers[i];
    }

    return *this;
}

然后可以使用现有的复制构造函数使用copy-swap idiom 使其更安全:

Array::Array(int num)
{
    size = num;
    numbers = new int[num];
    numberOfElements += num;
}

Array::Array(const Array &srcArray)
{
    size = src.size;
    numbers = new int[size];
    for (int i = 0; i < size; ++i)
        numbers[i] = srcArray.numbers[i];
    numberOfElements += size;
}

Array::~Array()
{
    delete[] numbers;
    numberOfElements -= size;
}

#include <algorithm>
Array& Array::operator=(const Array& newArray)
{
    if (this != &newArray)
    {
        if (size != newArray.size)
        {
            Array tmp(newArray);
            std::swap(numbers, tmp.numbers);
            std::swap(size, tmp.size);
        }
        else
        {
            for (int i = 0; i < size; ++i)
                numbers[i] = newArray.numbers[i];
        }
    }

    return *this;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-12
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    相关资源
    最近更新 更多