33

我意识到在调用vector.clear()which hold shared pointers 之后,拥有的对象的析构函数shared_ptr没有被释放。

代码示例如下所示。即使vector.clear()被调用,在共享指针之后调用的析构函数也超出了范围。我的问题是 - 我是否必须通过重置它们来手动删除向量内的所有智能指针?有没有更简单的方法可以提供建议?

Output :   

constructor
I am here
destructor

Code:

#include <vector>
#include <iostream>
#include <memory>

using namespace std;

class A
{
public:
    A(){cout << "constructor" << endl;};
    ~A(){cout << "destructor"  << endl;};
};

int main( )
{
    shared_ptr<A> sharedptr (new A);
    std::vector<shared_ptr<A> > test;
    test.push_back(sharedptr);

    test.clear();
    cout << "I am here" << endl;
}
4

4 回答 4

55

在这种情况下,您有两个副本shared_ptr<A>,一个是sharedptr变量,另一个是向量中的元素。

改为这样做

test.push_back(std::move(sharedptr));

请注意,现在原件sharedptr的内部已移动且不再可用。另一件事是根本不做任何事情,这是对 shared_ptr 的完全有效的用法,并且sharedptr会在超出范围后自行清理。

于 2013-10-12T13:52:25.470 回答
10

push_back将 的副本添加到shared_ptr向量时会出现问题,使原始悬空直到 main 存在。如果您不在主范围内创建 shared_ptr,则不会发生问题。只需避免将 shared_ptr 置于主范围内。使其成为push_back通话中的临时权利。

Output is now:   

constructor
I am almost there
destructor
I am here

New code:

#include <vector>
#include <iostream>
#include <memory>

using namespace std;

class A
{
public:
  A(){cout << "constructor" << endl;};
  ~A(){cout << "destructor"  << endl;};
};

int main( )
{
  vector<shared_ptr<A> > test;
  test.push_back(shared_ptr<A>(new A));
  cout << "I am almost there" << endl;
  test.clear();
  cout << "I am here" << endl;
  return 0;
}
于 2013-10-12T16:57:43.643 回答
4

这里sharedptr和vector中的元素共享同一个对象,这将导致只调用一次构造函数和析构函数。

于 2014-10-16T13:31:37.860 回答
1

直到稍后才调用析构函数的原因是您的变量sharedptrmain(). 如果你真的想在那之前清理它,有几种方法可以解决这个问题。解决此问题的最明显方法是仅sharedptr在快速块范围内使用:

int main( )
{
    std::vector<shared_ptr<A> > test;
    {
      shared_ptr<A> sharedptr (new A);
      test.push_back(sharedptr);
    }
    test.clear();
    cout << "I am here" << endl;
}

或者,永远不要创建sharedptr变量:

int main( )
{
    std::vector<shared_ptr<A> > test;
    test.push_back( shared_ptr<A>(new A) );
    test.clear();
    cout << "I am here" << endl;
}
于 2020-05-08T23:19:12.933 回答