shared_ptrs 被删除两次
shared_ptrs being deleted twice
我想在向量中存储指向 Object
class 的共享指针:
测试代码:
#include <vector>
#include <iostream>
#include <memory>
using namespace std; // only for brevity
class Object
{
public:
int n;
Object(int n) : n(n) { cout << "Object(" << n <<")\n"; }
~Object() { cout << "~Object(" << n << "))\n"; n = 0xdddddddd; }
};
void Test()
{
std::shared_ptr<Object> p1(make_shared<Object>(Object(123)));
std::vector<shared_ptr<Object>> v;
cout << "before push_back\n";
v.push_back(std::make_shared<Object>(Object(2)));
v.push_back(p1);
cout << "after push_back\n";
cout << "Vector content:\n";
for (auto& p : v)
cout << " " << p->n << "\n"; ;
}
int main()
{
Test();
cout << "after Test()\n";
}
输出为
Object(123)
~Object(123)) <<< why is the destructor called here?
before push_back
Object(2)
~Object(2)) <<< why is the destructor called here?
after push_back
Vector content:
2
123
~Object(2)) <<< destructor called again
~Object(123))
after Test()
我不明白为什么析构函数被调用两次。
OTOH矢量内容是我想要的。
I don't understand why the destructors are called twice.
因为在这里创建了不必要的临时对象:
std::shared_ptr<Object> p1(make_shared<Object>(Object(123)));
^^^
temporary object
这里:
v.push_back(std::make_shared<Object>(Object(2)));
^^^
temporary object
应该是
std::shared_ptr<Object> p1(make_shared<Object>(123));
和
v.push_back(std::make_shared<Object>(2));
为什么?
因为 std::make_shared
构造了一个 T 类型的对象并将其包装在一个 std::shared_ptr 中,使用 args 作为 T 的构造函数的参数列表。在您的代码中,您正在制作一个额外的对象它立即被销毁,从而调用析构函数。
为什么你看不到 Object(int n);
正在为临时对象调用构造函数?
Object(int n);
构造函数确实是为临时对象调用的,但是由于 std::shared_ptr
持有的对象是通过复制构造函数创建的(因此,通过复制临时对象)你不会请参阅对 Object(int n);
的调用,但对 Object(Object const& other);
.
的调用
在 demo 中,您可以看到首先为临时对象调用 Object(int n);
构造函数,然后为 Object(Object const& other);
引用的实际对象调用复制构造函数=17=].
这是因为您必须销毁临时值。
std::make_shared
函数接受任意数量的参数并用它构造给定类型的值。
你构造一个 Object
并将其传递给 std::make_shared
,后者又使用 new
构造一个值。然后,临时对象被销毁。后来,共享指针也被销毁了。
只需在您的代码中进行更改即可:
std::shared_ptr<Object> p1(make_shared<Object>(123));
// ...
v.push_back(std::make_shared<Object>(2));
并且您将看到每个值只有一个析构函数。
我想在向量中存储指向 Object
class 的共享指针:
测试代码:
#include <vector>
#include <iostream>
#include <memory>
using namespace std; // only for brevity
class Object
{
public:
int n;
Object(int n) : n(n) { cout << "Object(" << n <<")\n"; }
~Object() { cout << "~Object(" << n << "))\n"; n = 0xdddddddd; }
};
void Test()
{
std::shared_ptr<Object> p1(make_shared<Object>(Object(123)));
std::vector<shared_ptr<Object>> v;
cout << "before push_back\n";
v.push_back(std::make_shared<Object>(Object(2)));
v.push_back(p1);
cout << "after push_back\n";
cout << "Vector content:\n";
for (auto& p : v)
cout << " " << p->n << "\n"; ;
}
int main()
{
Test();
cout << "after Test()\n";
}
输出为
Object(123)
~Object(123)) <<< why is the destructor called here?
before push_back
Object(2)
~Object(2)) <<< why is the destructor called here?
after push_back
Vector content:
2
123
~Object(2)) <<< destructor called again
~Object(123))
after Test()
我不明白为什么析构函数被调用两次。
OTOH矢量内容是我想要的。
I don't understand why the destructors are called twice.
因为在这里创建了不必要的临时对象:
std::shared_ptr<Object> p1(make_shared<Object>(Object(123)));
^^^
temporary object
这里:
v.push_back(std::make_shared<Object>(Object(2)));
^^^
temporary object
应该是
std::shared_ptr<Object> p1(make_shared<Object>(123));
和
v.push_back(std::make_shared<Object>(2));
为什么?
因为 std::make_shared
构造了一个 T 类型的对象并将其包装在一个 std::shared_ptr 中,使用 args 作为 T 的构造函数的参数列表。在您的代码中,您正在制作一个额外的对象它立即被销毁,从而调用析构函数。
为什么你看不到 Object(int n);
正在为临时对象调用构造函数?
Object(int n);
构造函数确实是为临时对象调用的,但是由于 std::shared_ptr
持有的对象是通过复制构造函数创建的(因此,通过复制临时对象)你不会请参阅对 Object(int n);
的调用,但对 Object(Object const& other);
.
在 demo 中,您可以看到首先为临时对象调用 Object(int n);
构造函数,然后为 Object(Object const& other);
引用的实际对象调用复制构造函数=17=].
这是因为您必须销毁临时值。
std::make_shared
函数接受任意数量的参数并用它构造给定类型的值。
你构造一个 Object
并将其传递给 std::make_shared
,后者又使用 new
构造一个值。然后,临时对象被销毁。后来,共享指针也被销毁了。
只需在您的代码中进行更改即可:
std::shared_ptr<Object> p1(make_shared<Object>(123));
// ...
v.push_back(std::make_shared<Object>(2));
并且您将看到每个值只有一个析构函数。