【发布时间】:2019-12-04 06:22:14
【问题描述】:
我想模拟一段时间内的人口并保留仍然活着的个体的家谱(我不需要保留有关死去血统的数据)。世代是离散且不重叠的。为简单起见,我们假设繁殖是无性的,并且每个个体只有一个父母。这里是一堂课Individual
class Individual
{
public:
size_t nbChildren;
const Individual* parent;
Individual(const Individual& parent);
};
在我的Population 类中,我将有一个用于当前后代和当前父母(当前父母是上一代的后代)的向量。
class Population
{
private:
std::vector<Individual*> currentOffsprings;
std::vector<Individual*> currentParents;
public:
addIndividual(const Individual& parent) // Is called from some other module
{
Individual* offspring = new Individual(parent);
currentOffsprings.push_back(offspring);
}
void pruneDeadLineages() // At the end of each generation, get rid of ancestors that did not leave any offsprings today
{
// Collect the current parents that have not left any children in the current generation of offsprings
std::queue<Individual*> individualsWithoutChildren; // FIFO structure
for (auto& currentParent : currentParents)
{
if (currentParent->nbChildren() == 0)
{
individualsWithoutChildren.push(currentParent);
}
}
// loop through the FIFO to get rid of all individuals in the tree that don't have offspring in this generation
while (individualsWithoutChildren.size() != 0)
{
auto ind = individualsWithoutChildren.pop_front();
if (ind->nbChildren == 0)
{
ind->parent.nbChildren--;
if (ind->parent.nbChildren == 0)
{
individualsWithoutChildren.push(ind->parent);
}
delete ind;
}
}
}
void newGeneration() // Announce the beginning of a new generation from some other module
{
currentParents.swap(currentOffsprings); // Set offsprings as parents
currentOffsprings.resize(0); // Get rid of pointers to parents (now grand parents)
}
void doStuff() // Some time consuming function that will run each generation
{
for (auto ind : currentOffspings)
{
foo(ind);
}
}
};
假设我的代码的慢速部分将循环通过 doStuff 方法中的个体,我想在内存中保持个体连续,因此
std::vector<Individual*> currentOffsprings;
std::vector<Individual*> currentParents;
会变成
std::vector<Individual> currentOffsprings;
std::vector<Individual> currentParents;
现在的问题是我不想为在当前一代中没有留下任何后代的祖先消耗内存。换句话说,我不想为每一代保留人口中每代个体数量的整个长度向量。我想我可以实现一个 Individual 的析构函数,它什么都不做,这样祖父代的 Individuals 就不会在 void Population::newGeneration() 中的 currentOffsprings.resize(0); 行被杀死。然后在void Population::pruneDeadLineages() 中,我将使用Individual::destructor() 方法显式删除个人,而不是使用delete 或Individual::~Individual()。
傻吗?它会是内存安全的(或屈服于分段错误或内存泄漏)吗?我还有什么其他选择 1) 确保当前世代的个体在记忆中是连续的,并且 2) 我可以为没有留下任何后代的祖先释放这段连续记忆中的记忆?
【问题讨论】:
-
共享指针或弱指针是否适合您?可以在一定时间间隔内运行一些简单的清理,同时保持向量内存预分配到位
-
@PaulRenton 我没有使用共享指针和弱指针的经验,但我觉得它们无助于确保
Individuals在内存中是连续的,但我可能错了。谢谢 -
如果您希望它是连续的,则分配这些对象的池并使用弱指针引用从那里绘制指针。或者,覆盖一个新的运算符并创建一个内存池,当您分配您关心的对象时,该内存池保证是连续的。
标签: c++ memory data-structures memory-management tree