我正在编写一个执行差异进化的程序。有一次,我正在将我的解决方案分类到解决方案文件中,并遇到了这个问题。我的存档是一个结构 vector :
std::vector<SingleSolution> archive;
typedef struct SingleSolution
{
int *crop_area;
int *envf;
double nr_cost;
int env_cost;
int front;
int feasible;
} SingleSolution;
当我进行排序并有一个解决方案要放入我的存档时,我正在创建一个 SingleSolution 并将其推送到存档:
SingleSolution member;
member.crop_area = (int *)calloc(crops + 1, sizeof(int));
member.envf = (int *)calloc(M + 1, sizeof(int));
member.front = 1;
member.feasible = feasible[member1];
member.nr_cost = nr_costs[member1];
member.env_cost = env_costs[member1];
for (int n = 1; n <= crops; n++) member.crop_area[n] = solution_crop[member1][n];
for (int n = 1; n <= M; n++) member.envf[n] = solution_env[member1][n];
archive.push_back(member);
//free(member.crop_area);
//free(member.envf);
我在推送到 vector 后释放了这些数组,因为我认为它复制了我推送的内容,但在打印存档时我看到了明显的垃圾值并意识到了原因。如您所见,我已将其注释掉。
所以我的问题是,那个 push_back 到底发生了什么?它插入数组开始的内存位置,然后我释放那个空间?有什么方法可以克服这个问题,还是我需要在主函数中创建空间并在调用排序函数时传递它,然后在完成时释放它?
当你这样做时:
archive.push_back(member);
您要求它使用复制构造函数复制 member
到archive
vector 的末尾。您可以说“SingleSolution
中没有复制构造函数”,但实际上存在 - 编译器提供的复制构造函数,它生成结构成员的浅拷贝。这就是您的问题所在。您正在使用原始指针,默认的复制构造函数仅复制指针的值(它们指向的内存地址 - 您的缓冲区)。
当您尝试自己管理这些资源时,这是导致未定义行为或内存泄漏的好方法。当您释放缓冲区但仍有指向旧内存的指针时,您意识到了这一点。
让我们尝试用 C++ 重写这段代码。
首先,您不需要那个 typedef
。
其次,您的缓冲区可以替换为 std::vector
:
struct SingleSolution
{
std::vector<int> crop_area;
std::vector<int> envf;
double nr_cost;
int env_cost;
int front;
int feasible;
};
要填充你的结构,而不用担心内存分配/释放,你可以这样做:
SingleSolution member;
member.crop_area.resize(crops+1);
member.crop_area[0] = 0;
std::copy(&solution_crop[member1][1], &solution_crop[member1][crops+1], member.crop_area.begin()+1);
member.envf.resize(M+1);
member.envf[0] = 0;
std::copy(&solution_env[member1][1], &solution_env[member1][M+1], member.envf.begin()+1);
member.front = 1;
member.feasible = feasible[member1];
member.nr_cost = nr_costs[member1];
member.env_cost = env_costs[member1];
archive.push_back(member);
或者这个:
SingleSolution member;
member.crop_area.reserve(crops+1);
member.crop_area.push_back(0);
std::copy(&solution_crop[member1][1], &solution_crop[member1][crops+1], std::back_inserter(member.crop_area));
// or: std::copy_n(&solution_crop[member1][1], crops, std::back_inserter(member.crop_area));
member.envf.reserve(M+1);
member.envf.push_back(0);
std::copy(&solution_env[member1][1], &solution_env[member1][M+1], std::back_inserter(member.envf));
// or: std::copy_n(&solution_env[member1][1], M, std::back_inserter(member.envf));
member.front = 1;
member.feasible = feasible[member1];
member.nr_cost = nr_costs[member1];
member.env_cost = env_costs[member1];
archive.push_back(member);