1

我正在做一个练习题,问题要求创建一个析构函数以确保没有任何内存泄漏。当我使用此析构函数时,在执行 system("pause"); 后出现此错误:

http://imgur.com/r2bvF

这是复制构造函数:

    vector_of_int::vector_of_int ( const vector_of_int& a_vector )
    {
        an_array = new int[ a_vector.size ];

        this->size = a_vector.size;
        for( int i = 0; i < size; ++i )
        {
            an_array[i] = a_vector.an_array[i];
        }
    }

和赋值运算符:

    vector_of_int& vector_of_int::operator= ( const vector_of_int& a_vector )
    {
        if( this == &a_vector )
        {
            return *this;
        }

        this->size = a_vector.size;
        for( int i = 0; i < size; ++i )
        {
            an_array[i] = NULL;
            an_array[i] = a_vector.an_array[i];
        }
            return *this;
     }

我在网上搜索了一下,有人提到这可能是由于复制构造函数指向相同的内存位置。为了测试这一点,在我的 main() 函数中,我将数据推送到每个向量 a、b、c 中,然后重新打印它们,它们都是不同的。此错误在调用析构函数后显示并继续执行下一行 system("pause"); 在按任意键后,它会显示。这是 main() 的结尾:

    a_vector.~vector_of_int();
    b_vector.~vector_of_int();
    c_vector.~vector_of_int();
    cout << "\n";
    system("pause");
    return 0;

main.exe 在 main 的大括号结束后是否再次调用析构函数?当我评论所有 3 个析构函数语句时,错误不再显示。

谢谢。

4

4 回答 4

9

不要显式地调用析构函数,这将在对象超出范围时自动发生(从代码中,我相信给定.用于调用析构函数的符号,向量是堆栈分配的)。即使它们是在堆上分配的,使用new,您仍然不会显式调用析构函数,而是使用delete

此外,在赋值运算符this->size中更新但an_array不是。如果a_vector.size > this->size那样的话,它将导致越界访问,an_array因为它没有足够的元素:delete[]new[] an_array.

于 2012-07-03T19:56:23.840 回答
2

从代码中可以看出您正在显式调用析构函数。虽然这是合法的并且有一些用途,但通常你不应该显式调用析构函数,因为当对象超出范围(或被delete调用指针)时它们会自动调用。在已经销毁的对象上执行析构函数是未定义的行为。

在您的特定代码中,析构函数可能正在释放内存,第二次(在局部变量范围的末尾自动调用)它尝试释放已由您的手动调用释放并触发运行时错误的内存。

于 2012-07-03T19:58:31.030 回答
1

我想你已经像这样创建了你的向量:

vector_of_int v;

然后不要删除它 - 它是自动存储。它将在范围结束时自动删除

如果您将向量创建为:

vector_of_int *v = new vector_of_int();

致电delete运营商将其删除:

delete v;
于 2012-07-03T19:57:00.773 回答
1

在赋值运算符中,您将项目从一个数组复制到另一个数组。但是,如果本地数组的大小小于传递给运算符的参数怎么办?您将超过数组的大小。

于 2012-07-03T20:01:11.683 回答