认为我应该被允许“删除”一个指针,但抛出一个错误“正在使用中的块”
Thinking I should be allowed to `delete` a pointer but an error is thrown `block in use`
考虑这个函数:
bool RemoveElement(const T2& e2)
{
bool match = false;
for (int i = 0; i < _trenutno; i++)
{
if (*_elementi2[i] == e2){
match = true;
for (int j = i; j < _trenutno - 1; j++)
{
_elementi1[j] = _elementi1[j + 1];
_elementi2[j] = _elementi2[j + 1];
// SOLUTION: The two lines above are not correct.
// Instead of assigning addresses, I should have assigned
// values, ie. dereference them like below:
// *_elementi1[j] = *_elementi1[j + 1];
// *_elementi2[j] = *_elementi2[j + 1];
}
}
}
if (match)
{
_trenutno--;
//delete _elementi1[_trenutno];
_elementi1[_trenutno] = nullptr;
//delete _elementi2[_trenutno];
_elementi2[_trenutno] = nullptr;
}
return match;
}
仅供参考,指针本身(见下文)。我在上面的函数中尝试使用 delete
删除这对特定指针(最后一个元素)后面的值,否则我相信会发生内存泄漏?
template<class T1, class T2, int max>
class Kolekcija
{
T1* _elementi1[max];
T2* _elementi2[max];
int _trenutno;
public:
Kolekcija()
{
for (int i = 0; i < max; i++)
{
_elementi1[i] = nullptr;
_elementi2[i] = nullptr;
}
_trenutno = 0;
}
// ...
~Kolekcija()
{
for (int i = 0; i < _trenutno; i++){
delete _elementi1[i]; _elementi1[i] = nullptr;
delete _elementi2[i]; _elementi2[i] = nullptr;
}
}
// ....
为什么会这样,我想多了解一下,更好地理解指针。
这里你有很多问题,首先你需要删除item,然后为数组中的那个位置设置nullptr值,如果我想像你的情况一样使用T1和T2的数组,那么我会使用矢量而不是简单数组
如果您的 class 是 data owner
并且您想删除一些元素:
- 查找元素索引
(_elementi1[nFound] == searchValue)
- 从堆中删除这个元素
delete _elementi1[nFound];
- 将元素的值设置为
nullptr
_elementi1[nFound] = nullptr;
- 然后才移动尾随元素来代替删除的项目。
此序列将保护您免受 Remove
方法中的内存泄漏。
析构函数将清除其他堆分配的值(假设 _trenutno
是实际的 count
):
for (int i = 0; i < _trenutno; i++)
{
delete _elementi1[i]; _elementi1[i] = nullptr;
delete _elementi2[i]; _elementi2[i] = nullptr;
}
删除 nullptr
是 safe
。
所以我的 Remove()
版本:
bool RemoveElement(const T2& e2)
{
for (int i = 0; i < _trenutno; i++)
{
if (*_elementi2[i] == e2)
{
delete _elementi1[i];
_elementi1[i] = nullptr;
delete _elementi2[i];
_elementi2[i] = nullptr;
for (int j = i; j < _trenutno - 1; j++)
{
_elementi1[j] = _elementi1[j + 1];
_elementi2[j] = _elementi2[j + 1];
}
_trenutno--;
return true; //found
}
}
return false; //not found
}
我假设您的 collection 是 data owner
。所以你 have to
delete
所有传递给它的指针。
简单示例(我们添加 3 个值):
int* elements[max] = {0};
elements[0] = new int(4); //0x00FF1F
elements[1] = new int(5); //0x00FF2F
elements[2] = new int(6); //0x00FF3F
_trenutno = 3;
我们必须 delete
全部 3 int*
如果没有 Remove
被调用,析构函数将处理它(从 0
删除到 2
)。
如果我们调用Remove(5)
:
- 找到
5
值的索引 i == 1
- 调用
delete elements[1]
表示releaze memory at address 0x00FF2F
- 换班:
elements[1] = elements[2]
现在我们的数组是:
elements[0]; //0x00FF1F
elements[1]; //0x00FF3F
elements[2]; //0x00FF3F
并且 _trenutno = 2;
因此析构函数将删除从“0”到“1”的指针。
这就是删除的所有 3 个指针!
考虑这个函数:
bool RemoveElement(const T2& e2)
{
bool match = false;
for (int i = 0; i < _trenutno; i++)
{
if (*_elementi2[i] == e2){
match = true;
for (int j = i; j < _trenutno - 1; j++)
{
_elementi1[j] = _elementi1[j + 1];
_elementi2[j] = _elementi2[j + 1];
// SOLUTION: The two lines above are not correct.
// Instead of assigning addresses, I should have assigned
// values, ie. dereference them like below:
// *_elementi1[j] = *_elementi1[j + 1];
// *_elementi2[j] = *_elementi2[j + 1];
}
}
}
if (match)
{
_trenutno--;
//delete _elementi1[_trenutno];
_elementi1[_trenutno] = nullptr;
//delete _elementi2[_trenutno];
_elementi2[_trenutno] = nullptr;
}
return match;
}
仅供参考,指针本身(见下文)。我在上面的函数中尝试使用 delete
删除这对特定指针(最后一个元素)后面的值,否则我相信会发生内存泄漏?
template<class T1, class T2, int max>
class Kolekcija
{
T1* _elementi1[max];
T2* _elementi2[max];
int _trenutno;
public:
Kolekcija()
{
for (int i = 0; i < max; i++)
{
_elementi1[i] = nullptr;
_elementi2[i] = nullptr;
}
_trenutno = 0;
}
// ...
~Kolekcija()
{
for (int i = 0; i < _trenutno; i++){
delete _elementi1[i]; _elementi1[i] = nullptr;
delete _elementi2[i]; _elementi2[i] = nullptr;
}
}
// ....
为什么会这样,我想多了解一下,更好地理解指针。
这里你有很多问题,首先你需要删除item,然后为数组中的那个位置设置nullptr值,如果我想像你的情况一样使用T1和T2的数组,那么我会使用矢量而不是简单数组
如果您的 class 是 data owner
并且您想删除一些元素:
- 查找元素索引
(_elementi1[nFound] == searchValue)
- 从堆中删除这个元素
delete _elementi1[nFound];
- 将元素的值设置为
nullptr
_elementi1[nFound] = nullptr;
- 然后才移动尾随元素来代替删除的项目。
此序列将保护您免受 Remove
方法中的内存泄漏。
析构函数将清除其他堆分配的值(假设 _trenutno
是实际的 count
):
for (int i = 0; i < _trenutno; i++)
{
delete _elementi1[i]; _elementi1[i] = nullptr;
delete _elementi2[i]; _elementi2[i] = nullptr;
}
删除 nullptr
是 safe
。
所以我的 Remove()
版本:
bool RemoveElement(const T2& e2)
{
for (int i = 0; i < _trenutno; i++)
{
if (*_elementi2[i] == e2)
{
delete _elementi1[i];
_elementi1[i] = nullptr;
delete _elementi2[i];
_elementi2[i] = nullptr;
for (int j = i; j < _trenutno - 1; j++)
{
_elementi1[j] = _elementi1[j + 1];
_elementi2[j] = _elementi2[j + 1];
}
_trenutno--;
return true; //found
}
}
return false; //not found
}
我假设您的 collection 是 data owner
。所以你 have to
delete
所有传递给它的指针。
简单示例(我们添加 3 个值):
int* elements[max] = {0};
elements[0] = new int(4); //0x00FF1F
elements[1] = new int(5); //0x00FF2F
elements[2] = new int(6); //0x00FF3F
_trenutno = 3;
我们必须 delete
全部 3 int*
如果没有 Remove
被调用,析构函数将处理它(从 0
删除到 2
)。
如果我们调用Remove(5)
:
- 找到
5
值的索引i == 1
- 调用
delete elements[1]
表示releaze memory at address 0x00FF2F
- 换班:
elements[1] = elements[2]
现在我们的数组是:
elements[0]; //0x00FF1F
elements[1]; //0x00FF3F
elements[2]; //0x00FF3F
并且 _trenutno = 2;
因此析构函数将删除从“0”到“1”的指针。
这就是删除的所有 3 个指针!