shared_ptr不报告引用的对象删除

时间:2013-04-05 10:05:39

标签: c++ c++11 shared-ptr smart-pointers

我在MS Visual Studio 10中运行此代码,

#include <iostream>
#include <memory>
using namespace std;

class A
{
    int i;
public:
    A(int j) : i(j) {}
    ~A() {}
    void fun()
    {
        cout << "A::i = " << i << endl;
    }
};
int _tmain(int argc, _TCHAR* argv[])
{
    A aObj(12);
    std::shared_ptr<A> const pObj (&aObj,
                [] (A* pA) {
                    cout << "lambda deleter" << endl;
                });
    aObj.~A();
    pObj->fun();
    return 0;
}

这会打印/保存已删除的对象的数据成员,而不会报告任何类型的错误。

请写信:

  1. 为什么shared_ptr pObj没有报告(在运行时)底层对象已被删除?
  2. 由于我正在创建一个const shared_ptr,意味着不能使用它来引用任何其他对象,为什么在删除对象时不调用lambda。
  3. weak_ptr可以在类似情况下提供帮助。 weak_ptr与语义一起使用,即对象引用的生命周期超过它引用的对象。

1 个答案:

答案 0 :(得分:20)

  

为什么shared_ptr pObj不报告(在运行时)底层对象已被删除?

因为shared_ptr不是魔术 1 。只有当删除该对象时,它才知道何时删除了包含的对象。当您使用shared_ptr时,您已与shared_ptr签订了合同。该合同的其中一个租户(实际上,你用任何类型的智能指针输入的任何合同)是不能删除指针。 shared_ptr实例拥有指针, it 将删除它,而不是你。

违反该合同会导致未定义的行为。

  

由于我正在创建一个const shared_ptr,意味着不能使用它来引用任何其他对象,为什么在删除对象时不调用lambda。

同样,shared_ptr只能知道当删除所包含的对象时才会删除它。如果你违反合同,它对对象的状态一无所知。

  

weak_ptr可以在类似的情况下有所帮助。 weak_ptr与语义一起使用,即对象引用的生命周期超过它引用的对象。

weak_ptr不再是shared_ptr的神奇赋予。 weak_ptr只知道创建它的shared_ptr集合知道什么。如果shared_ptr不知道该对象已被删除,则weak_ptr也不会。


1 通过“魔术”,我的意思是做一些在C ++中无法做到的事情。如果你想知道一个函数被调用(析构函数是一个函数调用),那么只有两种方法可以做到。该函数告诉你它已被调用(通过设置你可以看到的值),或者你设置一个系统,人们调用你的函数,然后调用另一个函数。

第一个系统需要一个明确写入的函数,让人们知道它已被调用。你不能用任何旧功能做到这一点;它必须为此而设计。第二个系统要求每个人都使用你的新功能而没有人使用旧功能。如果有人直接使用旧代码,您的代码将无法了解它。

第一种方法称为“侵入式”(因为它要求您以特殊方式编写对象),使用它的智能指针称为“侵入式智能指针”。第二种方法是非侵入式的(不需要对象的特殊代码)。 shared_ptr和所有当前标准的智能指针都是非侵入式的。这意味着您可以将它们与任何对象一起使用,但只有遵守合同才能使用它们。

C ++不提供第三种方式。因此,一个可以以某种方式介入析构函数调用的类,一个可以知道它的类已被调用,而没有析构函数明确告诉它已经存在,是不可能的。因此会很神奇。