我想我不完全理解析构函数在C++中是如何工作的.这是我为重新创建问题而编写的示例程序:
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
struct Odp
{
int id;
Odp(int id)
{
this->id = id;
}
~Odp()
{
cout << "Destructing Odp " << id << endl;
}
};
typedef vector<shared_ptr<Odp>> OdpVec;
bool findOdpWithID(int id, shared_ptr<Odp> shpoutOdp, OdpVec& vec)
{
shpoutOdp.reset();
for (OdpVec::iterator iter = vec.begin(); iter < vec.end(); iter++)
{
Odp& odp = *(iter->get());
if (odp.id == id)
{
shpoutOdp.reset(iter->get());
return true;
}
}
return false;
}
int main()
{
OdpVec vec;
vec.push_back(shared_ptr<Odp>(new Odp(0)));
vec.push_back(shared_ptr<Odp>(new Odp(1)));
vec.push_back(shared_ptr<Odp>(new Odp(2)));
shared_ptr<Odp> shOdp;
bool found = findOdpWithID(0, shOdp, vec);
found = findOdpWithID(1, shOdp, vec);
}
Run Code Online (Sandbox Code Playgroud)
在main()结束之前,该程序的输出是:
Destructing Odp 0
Destructing Odp 1
Run Code Online (Sandbox Code Playgroud)
为什么会这样?我保留了对Odp向量中每个实例的引用.是否与传递shared_ptr引用有关?
更新我认为shared_ptr::reset根据MSDN递减引用计数:
运算符都减少当前由*this拥有的资源的引用计数
但也许我误解了它?
更新2:看起来这个版本findOdpWithID()不会导致析构函数被调用:
bool findOdpWithID(int id, shared_ptr<Odp> shpoutOdp, OdpVec& vec)
{
for (OdpVec::iterator iter = vec.begin(); iter < vec.end(); iter++)
{
Odp& odp = *(iter->get());
if (odp.id == id)
{
shpoutOdp = *iter;
return true;
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
ric*_*dwb 12
这条线路可能正在绊倒你.
shpoutOdp.reset(iter->get());
Run Code Online (Sandbox Code Playgroud)
你在这里做的是get()从智能指针获取(通过)裸指针,它不会有任何参考跟踪信息,然后告诉shpoutOdp重置自己指向裸指针.当shpoutOdp被破坏时,它不知道还有另一个shared_ptr指向同一个东西,并shpoutOdp继续破坏它所指向的东西.
你应该这样做
shpoutOdp = *iter;
Run Code Online (Sandbox Code Playgroud)
这将正确保持引用计数.顺便说一句,reset()确实递减参考计数器(并且只有在计数达到0时才会销毁).
| 归档时间: |
|
| 查看次数: |
2006 次 |
| 最近记录: |