【问题标题】:C++ Smart Pointers Scope and Resource DeletingC++ 智能指针范围和资源删除
【发布时间】:2020-07-29 16:35:36
【问题描述】:

我有以下简单的代码示例:

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

class resource
{
public:
   void print() { cout << "Class Still Alive" << endl; };
};

resource* create_resource()
{
   std::unique_ptr<resource> r = std::make_unique<resource>();
   return r.get();
}

void execute_resource(resource* r)
{
   r->print();
}

int main()
{
   resource* r = create_resource();
   execute_resource(r);
   return 0;
}

create_resource 中创建的唯一 ptr r 在函数末尾超出范围。至少这是我对范围的理解。

那么,由唯一指针包裹的实际资源如何仍然可以访问,并且确实会产生分段错误,因为它拥有的唯一指针应该已经超出范围并删除了它?

编译使用:g++ test.cpp -std=c++14

【问题讨论】:

    标签: c++ function scope c++14 smart-pointers


    【解决方案1】:

    是的,您对函数范围的理解是正确的。 std::unique_ptr&lt;resource&gt; 将在 create_resource 函数作用域之后被销毁。


    那么唯一指针仍然包裹的实际资源是如何 可达,并且确实会产生分段错误,因为它拥有唯一的 指针应该已经超出范围并删除了这个?

    由于上述原因,您在main这里收到的内容

    resource *r = create_resource();
    

    是一个悬空指针。访问它会导致undefined bahviour,因此任何事情都可能发生。在您的情况下,这是一个分段错误。


    为了解决此问题,您可以从 create_resource 函数返回 std::unique_ptr&lt;resource&gt; 本身

    #include <iostream>
    #include <utility>
    #include <memory>
    
    class resource
    {
    public:
       void print() const // can be const
       { 
             std::cout << "Class Still Alive\n";
       };
    };
    
    std::unique_ptr<resource> create_resource()
    {
       return std::make_unique<resource>(); // return the std::unique_ptr<resource>
    }
    
    void execute_resource(resource* r)
    {
       r->print();
    }
    
    int main()
    {
       auto r = create_resource();
       execute_resource(r.get()); // pass the pointer to execute!
       return 0;
    }
    

    【讨论】:

      【解决方案2】:

      在 create_resource() 中创建的唯一指针 r 超出范围 函数的结束。至少这是我对范围的理解。

      没错——当create_resource() 返回时,std::unique_ptr 的析构函数执行并删除它所持有的resource 对象。

      那么由唯一指针包裹的实际资源如何仍然 可达并且确实会产生分段错误,因为它拥有唯一的 指针应该已经超出范围并删除了这个?

      create_resource() 正在返回一个悬空指针——即指向之前resource 对象所在的内存位置的指针,但由于resource 对象已被删除,该指针不再可用。尝试取消引用悬空指针将导致未定义的行为,在某些情况下包括分段错误。

      处理这种情况的正确方法是让create_resource() 返回std::unique_ptr&lt;resource&gt; 而不是resource *

      【讨论】:

        【解决方案3】:

        在 create_resource() 中创建的唯一指针 r 在函数末尾超出范围。至少这是我对范围的理解。

        你的理解是正确的。

        那么由唯一指针包裹的实际资源如何仍然可以访问

        这个假设是错误的。函数返回后,它不再可访问。

        程序的行为未定义。它通过无效指针调用成员函数。

        【讨论】:

        • 感谢大家的回复。所以我要传达的信息是,上面的代码没有像我预期的那样触发段错误,这纯粹是因为它是未定义的行为,我只是“幸运”了成员函数仍然可以通过无效指针访问,因为你清楚地解释了以上。
        • @FieldtestoFieldtest 或“不幸”:)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-01-03
        • 1970-01-01
        • 2012-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-02
        相关资源
        最近更新 更多