【问题标题】:HugeInt error. Debug Assertion Failed巨大的整数错误。调试断言失败
【发布时间】:2015-06-10 11:57:50
【问题描述】:

我正在创建一个 HugeInt 类。我的主要:

#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
    HugeInt hi1("123");
    HugeInt hi2("456");

    std::cout << hi1 + hi2 << std::endl;

    return 0;
}

还有我的 HugeInt 类:

#include <iostream>
#include <string>

#define SIZE 32

class HugeInt
{
    friend std::ostream & operator<<(std::ostream &, const HugeInt &);

public:
    HugeInt();
    HugeInt(const char *);
    ~HugeInt();

    HugeInt operator+(const HugeInt &) const;
private:
    int * buffer;
    int size;
};

和他的方法:

HugeInt::HugeInt()
{
    size = SIZE;
    buffer = new int[size];

    for (int i = 0; i < size; i++) {
        buffer[i] = 0;
    }
}

HugeInt::HugeInt(const char * hugeNumber)
{
    size = strlen(hugeNumber);
    buffer = new int[size];

    for (int i = size - 1; i >= 0; i--) {
        buffer[i] = hugeNumber[i] - '0';
    }
}

HugeInt::~HugeInt()
{
    delete[] buffer;
}

HugeInt HugeInt::operator+(const HugeInt & operand) const
{
    HugeInt temp;

    int carry = 0;

    if (size >= operand.size)
        temp.size = size;
    else
        temp.size = operand.size;

    for (int i = 0; i < temp.size; i++) {
        temp.buffer[i] = buffer[i] + operand.buffer[i] + carry;

        if (temp.buffer[i] > 9) {
            temp.buffer[i] %= 10;
            carry = 1;
        }
        else {
            carry = 0;
        }
    }

    return temp;
}

std::ostream & operator<<(std::ostream & output, const HugeInt & complex)
{
    for (int i = 0; i < complex.size; i++)
        output << complex.buffer[i];
    return output;
};

一切都编译得很好。但控制台显示“-17891602-17891602-17891602”,然后出现错误“调试断言失败!....表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)”。

当我们重新定义 operator+() 时,问题出在“return temp”。它有什么问题?

【问题讨论】:

    标签: c++


    【解决方案1】:

    这段代码有很多错误

    您的主要问题是您正在按值返回一个类(在operator+ 的末尾)没有为它定义一个复制构造函数。您应该阅读Rule of 3(或其更新的咒语Rule of 5,甚至是Rule of 0)。

    基本上,由于您不进行深拷贝(为您提供的默认复制构造函数,因为您没有定义一个浅拷贝),所以您的原始 temp 和您实际的副本返回两个指向相同的buffer。当temp 的析构函数在函数末尾运行时(假设没有发生 NRVO),即使您返回的副本仍然指向它,它也会删除所述缓冲区。

    您可以通过添加正确的 复制构造函数 来解决此问题(因此满足规则 3),或者更好的解决方法是使用 std::vector&lt;int&gt; 而不是手动管理的缓冲区,这样就不会不需要复制构造函数或析构函数(零规则)。

    仅查看您的代码,还有一些问题。在您的添加函数中,您在不实际更改缓冲区的情况下摆弄temp 实例的size 成员。如果您碰巧将size 设置为大于分配的缓冲区,那么您将注销触发未定义行为的有效内存结束。

    Rule of 3/5/0 的有用链接

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-29
      • 2011-12-08
      • 2015-06-27
      相关资源
      最近更新 更多