动态数组 - 内存管理问题
Dynamic Array - Problem with memory management
我正在研究动态数组。数组相关部分代码 class:
#pragma once
#include <iostream>
template <class T>
class Darray
{
private:
T* dataArray;
int a_size = 0;
int a_capacity = 0;
double expandFactor = 1.5;
private:
void memLoc(int n_capacity)
{
T* newArray = new T[n_capacity];
for (int i = 0; i < a_size; i++)
{
newArray[i] = dataArray[i];
}
dataArray = newArray;
delete[] newArray; //<-- **************problem occurs here**************
a_capacity = n_capacity;
}
public:
Darray()
{
T* dataArray = new T[a_size];
memLoc(2);
}
void addLast(T data)
{
if (a_size < a_capacity)
{
dataArray[a_size] = data;
a_size++;
}
else
{
memLoc(a_capacity * expandFactor);
dataArray[a_size] = data;
a_size++;
}
}
当我 运行 代码 没有 删除 newArray 我得到预期的结果:
Values
Index 0: 10
Index 1: 9
Index 2: 8
Index 3: 7
Index 4: 6
Index 5: 5
Index 6: 4
Index 7: 3
Index 8: 2
Index 9: 1
这是我的问题! 当我删除 newArray(在代码中标记)时,我的结果远非准确:
Values
Index 0: -572662307
Index 1: -572662307
Index 2: 100663302
Index 3: 31812
Index 4: 17648624
Index 5: 17649832
Index 6: -572662307
Index 7: -572662307
Index 8: -572662307
Index 9: -572662307
我不知道为什么会这样,因为乍一看一切似乎都是正确的。任何建议或提示将不胜感激。我希望有人能够提供帮助 ;)
您的代码中有几个错误。
在 memLoc()
中,您正在破坏刚刚创建的 new 数组。您需要销毁正在替换的 old 数组。语句 dataArray = newArray;
只是将一个 指针 分配给另一个 指针 。 dataArray
指向前一个数组,newArray
指向新数组。当你执行 dataArray = newArray;
时,你泄漏了之前的数组,现在 dataArray
和 newArray
都指向同一个数组,然后 delete[] newArray;
破坏了那个数组,留下 dataArray
作为指向无效内存的悬空指针。
在您的默认构造函数中,您正在创建一个新数组并将其指针分配给名为 dataArray
的局部变量,该变量隐藏了也名为 class 的数据成员 dataArray
。然后调用 memLoc()
为 class 数据成员 dataArray
创建另一个数组以指向。第一个数组无用并被泄露。您应该将 class 数据成员初始化为 nullptr
,然后调用 memLoc()
来创建唯一的数组。
此外,虽然这些并不是每个人所说的错误,但它们值得注意:
我假设您未显示的其余代码符合 Rule of 3/5/0,即您有析构函数、copy/move 构造函数和 copy/move 赋值运算符。如果没有,请确保你解决了这个问题,否则你以后会 运行 陷入其他问题。
addLast()
中的代码重复,可以简化。
话虽如此,试试这个:
#pragma once
#include <iostream>
#include <utility>
template <class T>
class Darray
{
private:
T* dataArray = nullptr;
int a_size = 0;
int a_capacity = 0;
static const double expandFactor = 1.5;
private:
void memLoc(int n_capacity)
{
T* newArray = new T[n_capacity];
for (int i = 0; i < a_size; ++i)
{
newArray[i] = dataArray[i];
}
delete[] dataArray;
dataArray = newArray;
a_capacity = n_capacity;
}
public:
Darray()
{
memLoc(2);
}
Darray(const Darray &src)
{
memLoc(src.a_capacity);
for (int i = 0; i < src.a_size; ++i)
{
dataArray[i] = src.dataArray[i];
++a_size;
}
}
Darray(Darray &&src)
{
std::swap(dataArray, src.dataArray);
std::swap(a_capacity, src.a_capacity);
std::swap(a_size, src.a_size);
}
~Darray()
{
delete[] dataArray;
}
Darray& operator=(Darray rhs)
{
std::swap(dataArray, rhs.dataArray);
std::swap(a_capacity, rhs.a_capacity);
std::swap(a_size, rhs.a_size);
return *this;
}
void addLast(const T &data)
{
if (a_size >= a_capacity)
memLoc(a_capacity * expandFactor);
dataArray[a_size] = data;
++a_size;
}
...
};
我正在研究动态数组。数组相关部分代码 class:
#pragma once
#include <iostream>
template <class T>
class Darray
{
private:
T* dataArray;
int a_size = 0;
int a_capacity = 0;
double expandFactor = 1.5;
private:
void memLoc(int n_capacity)
{
T* newArray = new T[n_capacity];
for (int i = 0; i < a_size; i++)
{
newArray[i] = dataArray[i];
}
dataArray = newArray;
delete[] newArray; //<-- **************problem occurs here**************
a_capacity = n_capacity;
}
public:
Darray()
{
T* dataArray = new T[a_size];
memLoc(2);
}
void addLast(T data)
{
if (a_size < a_capacity)
{
dataArray[a_size] = data;
a_size++;
}
else
{
memLoc(a_capacity * expandFactor);
dataArray[a_size] = data;
a_size++;
}
}
当我 运行 代码 没有 删除 newArray 我得到预期的结果:
Values
Index 0: 10
Index 1: 9
Index 2: 8
Index 3: 7
Index 4: 6
Index 5: 5
Index 6: 4
Index 7: 3
Index 8: 2
Index 9: 1
这是我的问题! 当我删除 newArray(在代码中标记)时,我的结果远非准确:
Values
Index 0: -572662307
Index 1: -572662307
Index 2: 100663302
Index 3: 31812
Index 4: 17648624
Index 5: 17649832
Index 6: -572662307
Index 7: -572662307
Index 8: -572662307
Index 9: -572662307
我不知道为什么会这样,因为乍一看一切似乎都是正确的。任何建议或提示将不胜感激。我希望有人能够提供帮助 ;)
您的代码中有几个错误。
在
memLoc()
中,您正在破坏刚刚创建的 new 数组。您需要销毁正在替换的 old 数组。语句dataArray = newArray;
只是将一个 指针 分配给另一个 指针 。dataArray
指向前一个数组,newArray
指向新数组。当你执行dataArray = newArray;
时,你泄漏了之前的数组,现在dataArray
和newArray
都指向同一个数组,然后delete[] newArray;
破坏了那个数组,留下dataArray
作为指向无效内存的悬空指针。在您的默认构造函数中,您正在创建一个新数组并将其指针分配给名为
dataArray
的局部变量,该变量隐藏了也名为 class 的数据成员dataArray
。然后调用memLoc()
为 class 数据成员dataArray
创建另一个数组以指向。第一个数组无用并被泄露。您应该将 class 数据成员初始化为nullptr
,然后调用memLoc()
来创建唯一的数组。
此外,虽然这些并不是每个人所说的错误,但它们值得注意:
我假设您未显示的其余代码符合 Rule of 3/5/0,即您有析构函数、copy/move 构造函数和 copy/move 赋值运算符。如果没有,请确保你解决了这个问题,否则你以后会 运行 陷入其他问题。
addLast()
中的代码重复,可以简化。
话虽如此,试试这个:
#pragma once
#include <iostream>
#include <utility>
template <class T>
class Darray
{
private:
T* dataArray = nullptr;
int a_size = 0;
int a_capacity = 0;
static const double expandFactor = 1.5;
private:
void memLoc(int n_capacity)
{
T* newArray = new T[n_capacity];
for (int i = 0; i < a_size; ++i)
{
newArray[i] = dataArray[i];
}
delete[] dataArray;
dataArray = newArray;
a_capacity = n_capacity;
}
public:
Darray()
{
memLoc(2);
}
Darray(const Darray &src)
{
memLoc(src.a_capacity);
for (int i = 0; i < src.a_size; ++i)
{
dataArray[i] = src.dataArray[i];
++a_size;
}
}
Darray(Darray &&src)
{
std::swap(dataArray, src.dataArray);
std::swap(a_capacity, src.a_capacity);
std::swap(a_size, src.a_size);
}
~Darray()
{
delete[] dataArray;
}
Darray& operator=(Darray rhs)
{
std::swap(dataArray, rhs.dataArray);
std::swap(a_capacity, rhs.a_capacity);
std::swap(a_size, rhs.a_size);
return *this;
}
void addLast(const T &data)
{
if (a_size >= a_capacity)
memLoc(a_capacity * expandFactor);
dataArray[a_size] = data;
++a_size;
}
...
};