使用数组重载运算符“=”会导致运行时错误 C++

Posted

技术标签:

【中文标题】使用数组重载运算符“=”会导致运行时错误 C++【英文标题】:Overloaded Operator '=' using arrays gives a runtime error 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)显然是不正确的,因为新的大小可能与旧的大小不同,所以有时你写的越界 第二个版本更好(虽然它应该检查自赋值并且不是异常安全的);如果它似乎不起作用,那么您可能在程序的其他地方有一个错误(这可能是一个自分配调用)。我建议使用第二个版本,如果您仍然遇到问题,请发布***.com/help/minimal-reproducible-example 如果你的复制构造函数工作正常,而你的析构函数工作正常,那么赋值运算符就变成了使用copy / swap的3行代码。请出示您的复制构造函数。 为什么numberOfElements 是静态的?那是一整套自己的错误 【参考方案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;

【讨论】:

以上是关于使用数组重载运算符“=”会导致运行时错误 C++的主要内容,如果未能解决你的问题,请参考以下文章

尝试在模板类中重载 / 运算符的 C++ 错误

c++中为啥赋值运算符重载返回类型是引用

C++ 重载数组运算符

C++ 输入运算符重载

C++ 作业 - 使用动态数组重载 >> 运算符

小于运算符不能作为成员函数重载