代码之家  ›  专栏  ›  技术社区  ›  mahesh

使用另一个指针对“unique”(唯一)指针拥有的对象调用“delete”(删除)

  •  1
  • mahesh  · 技术社区  · 6 年前

    我有一个指向类的指针,该类由 new 操作员。然后我用这个指针设置 std::unique_ptr . 现在,根据我的理解,一旦手动调用 delete 运算符,然后当唯一指针超出范围时。此代码如何“正确”运行,即,没有运行时异常?

    #include <iostream>
    #include <memory>
    
    class A
    {
    public:
        A()
        {
            std::cout<<"In A::A()\n";
        }
        ~A()
        {
            std::cout<<"In A::~A()\n";
        }
        void printMyStr()
        {
            std::cout<<"In A::printMyStr()\n";
        }
    };
    
    int main()
    {
        std::cout<<"hello world!\n";
        A * pa = new A();
        std::unique_ptr<A> upa(pa);
        pa->printMyStr();
        upa->printMyStr();
        delete pa;  // How does this not create problems?
        return 0;
    }
    

    输出:

    hello world!
    In A::A()
    In A::printMyStr()
    In A::printMyStr()
    In A::~A()
    In A::~A()
    

    显然,析构函数运行两次,即使只创建了一个对象。这怎么可能?

    注意:我在64位Linux上使用GCC7.3.0。

    2 回复  |  直到 6 年前
        1
  •  3
  •   Yakk - Adam Nevraumont    6 年前

    双重删除是未定义的行为。

    未定义的行为不能保证运行时异常;该woukd是被定义的。未定义的行为意味着任何事情都可能发生。这可以包括时间旅行、格式化硬盘、通过电子邮件向联系人发送浏览器历史记录,或者什么都不做。

    据我所知,我还没有经历过浏览器的历史记录。其余的我都经历过了。

        2
  •  0
  •   Roman Odaisky    6 年前

    如果在唯一的指针实例超出作用域之前的某个时刻决定要删除托管对象,只需执行 unique_ptr_instance.reset(nullptr) . 这会调用deleter并导致托管对象变为nullptr,当实例最终超出作用域时,删除该对象是一个no-op。