【发布时间】:2015-09-23 00:23:09
【问题描述】:
以下代码构成MCVE,这重现了我想问的问题,但它不是真正的代码。真正的代码要复杂得多,所以我写这个是为了演示这个问题。
我正在寻找的关键功能是能够增长动态分配的数组,请不要建议使用stl,因为它被明确禁止。此代码用于教育目的,因此存在限制。
#include <cstring>
#include <iostream>
class Value
{
public:
Value(int value = 0);
Value(const Value &value);
Value &operator =(const Value &other);
~Value();
operator int() {return *m_absurdPointer;}
private:
int *m_absurdPointer;
};
Value::Value(int value) :
m_absurdPointer(new int[1])
{
*m_absurdPointer = value;
}
Value::Value(const Value &value)
{
m_absurdPointer = new int[1];
memcpy(m_absurdPointer, value.m_absurdPointer, sizeof(*m_absurdPointer));
}
Value &Value::operator =(const Value &other)
{
m_absurdPointer = new int[1];
memcpy(m_absurdPointer, other.m_absurdPointer, sizeof(*m_absurdPointer));
return *this;
}
Value::~Value()
{
delete[] m_absurdPointer;
}
class ValueArray
{
public:
ValueArray();
~ValueArray();
void append(const Value &value);
void show() const;
private:
Value *m_array;
unsigned int m_capacity;
unsigned int m_length;
};
ValueArray::ValueArray() :
m_array(nullptr)
, m_capacity(0)
, m_length(0)
{
}
ValueArray::~ValueArray()
{
delete[] m_array;
}
void
ValueArray::append(const Value &value)
{
if (m_length >= m_capacity)
{
Value *newarray;
unsigned int unitSize;
unitSize = 1;
newarray = new Value[m_capacity + unitSize];
if ((m_capacity > 0) && (m_array != nullptr))
memcpy(newarray, m_array, m_capacity * sizeof(*m_array));
delete[] m_array;
m_array = newarray;
m_capacity += unitSize;
}
m_array[m_length++] = value;
}
void
ValueArray::show() const
{
for (size_t i = 0 ; i < m_length ; ++i)
std::cout << static_cast<int>(m_array[i]) << std::endl;
}
int
main(void)
{
ValueArray example;
for (int i = 0 ; i < 10 ; ++i)
example.append(Value(i));
example.show();
return 0;
}
如您所见,它会导致双重 free 问题,因为 delete[] m_array; 在将值复制到 re-newed 数组后调用了类 Value 的析构函数。
我尝试使用malloc()/realloc() 执行此操作,但我需要调用Value() 的析构函数,因此new 是强制性的,因为我不能使用free()。
如何防止这种情况发生?如果我删除delete[] m_absurdPointer;,双重释放当然会消失,但会有内存泄漏。
【问题讨论】:
-
你可以强制 new 在给定的空间块中分配一些东西,例如
new (memblockPtr) SomeType() -
@iharob,我想说您将 ValueArray 实现为链接列表。您不必使用这种方法重新分配内存,并且您想做的所有其他事情 - 据我所知 - 可能(即使具有相同的运行时限制)
-
@iharob,如果您担心在使用节点时分配过于频繁,请先分配一堆节点并从该池中提取,直到您用完节点等...
-
@WorldSEnder 我想我不能因为我需要在数据上做一个
bsearch(),所以我想跳过列表会是一个更好的方法,但我认为这是不允许的. -
@iharob,如果你需要二分查找,那么二叉树呢?还要解释一下荒谬的指针,因为它有点没用
标签: c++ design-patterns new-operator delete-operator