问题情境:
最近想要通过实现一个非常简单的线程池来练习编程思维(把想法转换成流程图?,然后将流程图转换成代码)。现实再一次提醒了自己是有多么菜。看似一个简单的东西,花了好久去实现,过程中发现自己对于好多小的知识点一点都不熟练,比如 STL容器!!!
在我的代码中有:
class Job{
Job(_param_){
...
param = (LPVOID)malloc(size);
}
~Job(){
free(param);
LPVOID param;
LPFUNC func;
};
使用list<Job*> jobList; 来保存任务。
还有一个函数 GetJob(Job** pJob){...}
第一个问题:
在这个函数中,当有待执行的任务时,将通过指针从jobList中弹出一个任务,当使用pop_front/remove/erase时,都会导致容器中的对象被删除,所以这是通过这个指针返回的对象在实际执行中会发生访问无效内存空间的错误!!!
第二个问题:
在执行~Job(){...} 时,会发生内存访问错误!!!
导致这个问题的原因: 在STL容器删除对象的时候已经free过了?
有一个疑问,不是删除Job对象的时候应该会调用Job的析构函数吗?为什么在实际调用的时候会产生错误呢?
这是STL中碰到的问题!
很简单,但是在实际使用中是很容被忽略的问题!
第三个问题:
由于返回的是指针,所以在将对象从jobList中删除之前需要将Job的对象复制一份!
又由于Job对象中有从堆中分配的空间,所以如果使用默认的拷贝构造函数,系统只会默认的复制 param的地址,而不会重新分配一个空间给新对象的param然后再将param空间中的内容拷贝过来,因此在该Job对象被从容器中删除的时候,由默认拷贝构造函数产生的对象中的param所指向的内容将变成无效内存空间!
解决办法:
这个时候我们需要定义自己的拷贝构造函数,然后在函数中为新的对象中的param指针分配一个新的空间,然后将旧的对象中的内容复制过来!如代码:
class Job{
Job(Job& job){
paramsize = job.paramsize;
func = job. func;
param = (LPVOID)malloc(paramsize);
RtlCopyMemory(param,job.param,paramsize);
}
LPVOID param;
LPFUNC func;
int paramsize;
}
很多时候我们学习了很多东西,但我们知其然却不知其所以然!
很早之前就学习过了拷贝构造函数,深拷贝,浅拷贝,但是可能忘记了,可能没有深入的理解深拷贝,浅拷贝产生的原因和使用的场景!
知其然,也要知其所以然!