C++ 如何解决此内存泄漏

C++ 如何解决此内存泄漏,c++,memory-leaks,C++,Memory Leaks,我试图重新创建vector类,我相信我的代码中存在内存泄漏,但我不知道如何解决它。在我的VisualStudio中使用CRT库,它告诉我每次调用reserve时都会出现一个假定的内存泄漏 我不太清楚这是为什么,或者是否有内存泄漏。内存泄漏检测表明这是reserve函数中的这一行int*temp=new int[n] 据我所知,这是在储备功能中发生的情况: 一旦arr的内容被复制到temp中,就可以删除arr了。分配arr=temp应该可以工作,因为我所做的就是将arr指向temp所在的位置。因为

我试图重新创建vector类,我相信我的代码中存在内存泄漏,但我不知道如何解决它。在我的VisualStudio中使用CRT库,它告诉我每次调用reserve时都会出现一个假定的内存泄漏

我不太清楚这是为什么,或者是否有内存泄漏。内存泄漏检测表明这是reserve函数中的这一行int*temp=new int[n]

据我所知,这是在储备功能中发生的情况:

一旦arr的内容被复制到temp中,就可以删除arr了。分配arr=temp应该可以工作,因为我所做的就是将arr指向temp所在的位置。因为arr以前被删除了,所以堆中只有1个数组,而且arr和temp都指向同一个数组,所以应该没有内存泄漏。Temp不重要,因为它在退出作用域后消失。在后续调用reserve函数时,每件事情都会重复,并且堆中应该只有一个arr指向的数组

我相信我的想法在某种程度上可能是错误的

    #include "Vector.h"

    namespace Vector {

    vector::vector() {
        sz = 0;
        space = 0;
        arr = nullptr;
    }
    vector::vector(int n) {
        sz = n;
        space = n;
        arr = new int[n];
        for(int i = 0; i < n; i++) {
            arr[i] = 0;
        }
    }
    void vector::push_back(int x) {
        if(sz == 0) {
            reserve(1);
        } else if (sz == space) {
            reserve(2*space);
        }
        arr[sz] = x;
        sz++;
    }
    void vector::reserve(int n) {
        if (n == 1) {
            arr = new int[1]; //arr was a nullptr beforehand
        }
        int* temp = new int[n]; 
        for(int i = 0; i < n; i++) {
            temp[i] = arr[i];
        }
        delete[] arr;
        arr = temp;
        space = n;      
    }

#包括“Vector.h”
名称空间向量{
向量::向量(){
sz=0;
空间=0;
arr=nullptr;
}
向量::向量(int n){
sz=n;
空间=n;
arr=新整数[n];
对于(int i=0;i
我也有同样的问题。我在堆中创建了两个指向同一地址的指针。当我试图释放内存时,结果只有一个指针可以释放内存,它是指向该地址的第一个指针。指向该地址的第二个或第三个指针没有释放内存的权限奥利,但只有第一批拥有这种权力的人

范例

int *a = new int[5];
int *b = a;
int *c = a;
指针b和c也没有权限释放指针a指向的内存地址。因此,如果我说的是
delete[]b
delete[]c
,则内存没有释放权限。然后我尝试编写
delete[]一个
成功了。我没有真正的答案,我只是试图通过我所做的尝试和错误来接近。这就是我得到的


<>实际上这个案例违反了规则,但是C++仍然允许我们这样做,它被称为未定义行为。我们违反了Dele[]/Calp>运算符的规则,但是C++仍然允许你这样做,结果,你得到了意想不到的输出。

你的代码假设在<代码> vector::该

arr
null

void vector::reserve(int n) {
    if (arr) { //handle case when arr is null
        space += n;
        arr = new int[space];
        //no need to copy anything!
    } else { //handle case when arr is not null
        int* tmp(new int[space + n]);
        for(int i = 0; i < space; i++) {
            tmp[i] = arr[i];
        }
        delete[] arr;
        arr = tmp;
        space += n;
    }
}
相反,可能会根据
arr
是否为
null
来划分
reserve
的功能

void vector::reserve(int n) {
    if (arr) { //handle case when arr is null
        space += n;
        arr = new int[space];
        //no need to copy anything!
    } else { //handle case when arr is not null
        int* tmp(new int[space + n]);
        for(int i = 0; i < space; i++) {
            tmp[i] = arr[i];
        }
        delete[] arr;
        arr = tmp;
        space += n;
    }
}
void vector::reserve(int n){
if(arr){//处理arr为null时的情况
空间+=n;
arr=新整数[空间];
//不需要复制任何东西!
}else{//处理arr不为null时的大小写
int*tmp(新int[space+n]);
for(int i=0;i

此外,上面的代码假定您的意思是保留
空格+n
,而不是允许
保留
收缩数组,因为如果保留的数据少于以前的保留,则会丢失数据。通常更好的做法是在使用指针时不使用关于指针状态的假设,因为当代码变得更复杂时,假设离子最终可能会被遗忘或变得更加模糊。

这里没有太多错误

漏洞 注释无法保证。没有什么可以阻止多次调用resize,包括调用
reserve(1)
,这将泄漏
arr
指向的任何内存。请考虑

    if (arr == nullptr) {
        arr = new int[n]; //arr was a nullptr beforehand
    }
现在这个评论肯定是真的

每次阵列大小增加时,复制循环都会超出
arr
的末端

    for(int i = 0; i < n; i++) {
        temp[i] = arr[i];
    }
检查
n
sz
,以防止两端溢出和复制尚未设置的数据。如果没有要复制的内容,则全部完成

机会目标 该类需要一个析构函数来释放它所拥有的任何内存(),如果没有它,就会发生泄漏

vector::~vector() {
    delete[] arr;
}
如果它有析构函数,则要求它具有特殊的支持函数来处理(至少)类的复制,或者明确禁止复制

// exchanges one vector for the other. Generally useful, but also makes moves 
// and assignments easy
void vector::swap(vector& a, vector& b)
{
    std::swap(a.sz, b.sz);
    std::swap(a.space, b.space);
    std::swap(a.arr, b.arr);
}

// Copy constructor
vector::vector(const vector& src):
    sz(src.sz),
    space (src.space),
    arr(new int[space])
{
    for(int i = 0; i < sz; i++) {
        arr[i] = src.arr[i];
    }
}

// move constructor
vector::vector(vector&& src): vector()
{
    swap(*this, src);
}

// assignment operator
vector::vector& vector::operator=(vector src)
{
    swap(*this, src);

    return *this;
}
//用一个向量交换另一个向量。通常很有用,但也可以移动
//作业也很简单
无效向量::交换(向量a、向量b)
{
标准:掉期(a.sz,b.sz);
交换(a空间,b空间);
标准::交换(a.arr,b.arr);
}
//复制构造函数
向量::向量(常量向量和src):
深圳(src.sz),
空间(src.space),
arr(新整数[空间])
{
对于(int i=0;i
复制构造函数使用。这是有趣的

赋值运算符使用。这不是实现赋值运算符的最快方法,但可能是最简单的方法。从“易”开始,如果容易,则只转到“难”
// exchanges one vector for the other. Generally useful, but also makes moves 
// and assignments easy
void vector::swap(vector& a, vector& b)
{
    std::swap(a.sz, b.sz);
    std::swap(a.space, b.space);
    std::swap(a.arr, b.arr);
}

// Copy constructor
vector::vector(const vector& src):
    sz(src.sz),
    space (src.space),
    arr(new int[space])
{
    for(int i = 0; i < sz; i++) {
        arr[i] = src.arr[i];
    }
}

// move constructor
vector::vector(vector&& src): vector()
{
    swap(*this, src);
}

// assignment operator
vector::vector& vector::operator=(vector src)
{
    swap(*this, src);

    return *this;
}