一般来说,您应该永远不要在 C++ 中手动管理内存。这将导致泄漏、双重删除和所有kinds of nasty inconveniences。为此使用适当的资源处理类。例如,std::vector 用于管理动态分配的数组。
要回到手头的问题,您首先需要知道delete [] _perm[i] 做了什么:它为该数组中的每个Chromosome 对象调用析构函数,然后释放内存。现在您在循环中执行此操作,这意味着这将调用 all Chromosome 析构函数并执行 f 释放。正如在对您的问题的评论中已经提到的那样,非常Chromosome析构函数是真正的罪魁祸首。尝试对此进行调查。
但是,您可以更改内存处理以提高分配和解除分配的速度。 As Nawaz has shown,您可以分配一大块内存并使用它。我会使用std::vector 作为缓冲区:
void f(std::size_t row, std::size_t col)
{
int sizeMemory = sizeof(Chromosome) * row * col;
std::vector<unsigned char> buffer(sizeMemory); //allocation of memory at once!
vector<Chromosome*> chromosomes(row);
// use algorithm as shown by Nawaz
std::size_t j = 0 ;
for(std::size_t i = 0 ; i < row ; i++ )
{
//...
}
make_baby(chromosomes); //use chromosomes
in_place_destruct(chromosomes.begin(), chromosomes.end());
// automatic freeing of memory holding pointers in chromosomes
// automatic freeing of buffer memory
}
template< typename InpIt >
void in_place_destruct(InpIt begin, InpIt end)
{
typedef std::iterator_traits<InpIt>::value_type value_type; // to call dtor
while(begin != end)
(begin++)->~value_type(); // call dtor
}
然而,尽管通过 std::vector 处理所有内存这仍然不是完全异常安全的,因为它需要显式调用 Chromosome 析构函数。 (如果make_baby() 抛出异常,函数f() 将提前中止。虽然向量的析构函数将删除它们的内容,但一个只包含指针,另一个将其内容视为原始内存。没有守卫在看在该原始内存中创建的实际对象。)
我能看到的最佳解决方案是使用一维数组包装在一个允许二维访问 到该数组中的元素。 (毕竟,在当前硬件上,内存是一维的,所以系统已经在这样做了。)这是一个草图:
class chromosome_matrix {
public:
chromosome_matrix(std::size_t row, std::size_t col)
: row_(row), col_(col), data_(row*col)
{
// data_ contains row*col constructed Chromosome objects
}
// note needed, compiler generated dtor will do the right thing
//~chromosome_matrix()
// these rely on pointer arithmetic to access a column
Chromosome* operator[](std::size_t row) {return &data_[row*col_];}
const Chromosome* operator[](std::size_t row) const {return &data_[row*col_];}
private:
std::size_t row_;
std::size_t col_;
std::vector<chromosomes> data_
};
void f(std::size_t row, std::size_t col)
{
chromosome_matrix cm(row, col);
Chromosome* column = ch[0]; // get a whole column
Chromosome& chromosome1 = column[0]; // get one object
Chromosome& chromosome2 = cm[1][2]; // access object directly
// make baby
}