做为一个苦逼的程序员,你不得不接受同事代码的摧残,因为你没办法改变别人的习惯只能改变自己。
所以今天介绍一下,使用别人的自定义类的苦逼问题。
class G
{
public:
G();
~G();
private:
int a;
vector<string>b;
};
G::G()
{
}
G::~G()
{
}
class F
{
public:
F();
~F();
void SetG(G* g) { haoQi = g; }
void SetInt(int x) { fanPerson = x; }
private:
int fanPerson;
G* haoQi = nullptr;
};
F::F()
{
}
F::~F()
{
if (haoQi)
{
delete haoQi;
haoQi = nullptr;
}
}
vector<F> example()
{
F youDU;
G* zhengDu = new G;
youDU.SetG(zhengDu);
youDU.SetInt(1);
vector<F>vF;
vF.emplace_back(youDU);
return vF;
}
大概是这么一个类。(不能截取项目代码这是职业操守。)
在使用的时候,很明显,他没有进行new的操作,所以指针得你自己new。然后调用函数传入对象中。那么以上代码有多少错误,哪里必然崩溃呢?
1.首先的首先,没有new的话那么F必然是个局部变量,那么你传出去一个局部的变量,有意义吗?要知道在出大括号的时候必然会释放的变量,你做的操作多半是有问题的,当然可能你会想,我返回的是vector啊。而且听说vector有魔力啊。
2.这就是重点,拿起你的笔记,考点来了。vector确实会在emplace的时候进行一次构造复制调用,可是你也没写啊。(push-back和emplace-back的区别感兴趣自己百度下。)
3.特别的,你new了指针传给它怎么没delete啊。这个比较简单。因为析构里面写了,管起来了,这个只是说说玩。
那么改吧。
class G
{
public:
G();
~G();
private:
int a;
vector<string>b;
};
G::G()
{
}
G::~G()
{
}
class F
{
public:
F();
~F();
void SetG(G* g) { haoQi = g; }
void SetInt(int x) { fanPerson = x; }
private:
int fanPerson;
G* haoQi = nullptr;
};
F::F()
{
}
F::~F()
{
if (haoQi)
{
delete haoQi;
haoQi = nullptr;
}
}
vector<F*> example()
{
F *youDU=new F;
G* zhengDu = new G;
youDU->SetG(zhengDu);
youDU->SetInt(1);
vector<F*>vF;
vF.emplace_back(youDU);
return vF;
}
看明白了吗?
特别的,因为没有复制构造函数,在调用vector的方法时,如果进行扩容,无论是emplaceback还是pushback都会有一个resize的过程,其中会对与原有的变量进行释放,调用析构,如果有指针,那么你的指针没有指向正确的,调用的是默认复制构造函数。那么就会出现多次释放的问题。在析构时出现错误。
表现为...算了别懒了在写一个。
vector<vector<F*>> example()
{
vector<F*>vF;
vector<vector<F*>> vFF;
for (int i=0;i<10;i++)
{
F *youDU = new F;
G* zhengDu = new G;
youDU->SetG(zhengDu);
youDU->SetInt(1);
vF.emplace_back(youDU);
vFF.emplace_back(vF);
vF.clear();
}
return vFF;
}
在执行到第二次循环时,vFF.emplace_back(vF),会崩溃(F没有new的话)。
指针有很多和内存相关的问题,值得我一个C++两个月的菜逼,记录一下。
忙着下班,如果有错误欢迎指正和讨论。
下一次可能就是STL源码相关的文章,因为发现STL坑挺多。