C++:为什么要在这里调用析构函数?

标签 c++ destructor

我想我并不完全理解析构函数在 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);
}

就在 main() 结束之前,这个程序的输出是:

Destructing Odp 0
Destructing Odp 1

为什么会这样?我保留了对 vector 中每个 Odp 实例的引用。它与通过引用传递 shared_ptr 有什么关系吗?

更新 我认为 shared_ptr::reset 减少了引用计数,基于 MSDN :

The operators all decrement the reference count for the resource currently owned by *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;
}

最佳答案

这里的这条线可能会让您感到困惑。

shpoutOdp.reset(iter->get());

你在这里做的是(通过 get())从智能指针获取裸指针,它上面没有任何引用跟踪信息,然后告诉 shpoutOdp 将自身重置为指向裸指针。当 shpoutOdp 被破坏时,它不知道还有另一个 shared_ptr 指向相同的东西,并且 shpoutOdp 继续破坏它所指向的东西到。

你应该这样做

shpoutOdp = *iter;

这将正确维护引用计数。顺便说一句,reset() 确实会减少引用计数器(并且仅在计数为 0 时才销毁)。

关于C++:为什么要在这里调用析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3214837/

相关文章:

c++ - 局部静态变量的销毁

C++ 单例构造函数和析构函数

c++ - 使用 ostringstream 语法将字符串加倍

c++ - 由于 Unresolved external 问题,OpenCV 无法编译 -- LNK2019

c++ - 为什么 QPainter 在 QAbstractItemView::dataChanged 中不工作?

c++析构函数,何时何地?

c++ - 如何使用 cmake 在我的代码中包含一个库?

c++ - 在 MFC 应用程序中定义和读取用户定义的资源

c++ - std::list 的 erase 成员函数是否为所有存储的元素调用析构函数?

c++ - std::map 如何调用值析构函数?