shared_ptr不报告引用的对象删除

mas*_*asT 2 c++ smart-pointers shared-ptr c++11

我在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;
}
Run Code Online (Sandbox Code Playgroud)

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

请写信:

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

Nic*_*las 20

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

因为shared_ptr不是魔法1.它知道何时删除包含的对象只有在删除该对象时.当你使用a时shared_ptr,你已经签订了合同shared_ptr.该合同的租户之一(实际上,您使用任何类型的智能指针进入的任何合同)是无法删除指针.该shared_ptr实例拥有指针,并且会删除它,而不是你.

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

由于我正在创建一个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++没有提供第三种方式.因此,一个可以以某种方式介入析构函数调用的类,一个可以知道它的类已被调用,而没有析构函数明确告诉它已经存在,这是不可能的.因此将是魔术.