【问题标题】:Smart pointers to an object explicitly created object指向对象的智能指针显式创建的对象
【发布时间】:2021-05-18 11:04:47
【问题描述】:

我已经阅读了很多与此相关的问题,但无法回答我的问题。

我创建了一个类如下-

class exampleClass{
public: 
    exampleClass(int n){
        cout<<"Created Class"<<endl;
        this->number = n;
    }

    ~exampleClass(){
        cout<<endl<<"This class is destroyed Now"<<endl;
    }

    template<typename t> t 
    addNum(t a, t b){
        return a + b;
    }

    void print(){
        cout<<this->number<<endl;
    }
private:
    int number;
};

我制作了 2 个shared_ptr(或就此而言unique_ptr,错误相同)如下 -

int main(){
   exampleClass* object = new exampleClass(60);

   std::shared_ptr<exampleClass> p1(object);
   std::shared_ptr<exampleClass> p2 (object);
   p1->print();
}

现在它最后抛出的错误是 -

free(): double free detected in tcache 2
Aborted (core dumped)

我无法理解为什么最后会出现错误。上面的代码不应该等于p2 =p1(在shared_ptr的情况下)或p2 = std::move(p1)对于unique_ptr,因为两个指针都指向同一个对象?

TIA
PS - 标题可能有点误导或不准确,但我不知道到底应该是什么标题。

【问题讨论】:

  • 如果你编码了 p2 = object,编译器如何猜测 p2 = p1?它完全按照您的编码完成。
  • 从原始指针创建 shared_ptrunique_ptr 意味着创建的智能“指针”现在拥有指向的对象,并且您不能将所有权移交给其他任何对象. (这有点像送你的车;你只能这样做一次,然后新主人就可以决定如何处理它。)
  • 您已经了解了代码中应该出现 0 次 new 的原因之一。

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


【解决方案1】:

当您创建一个智能指针时,它将获得指针的所有权,并在超出范围时将其删除(或者在共享指针的情况下完成最后一次引用时)。 当您从同一个原始指针创建两个智能指针时,它们都会在生命结束时删除指针,因为它们彼此不知道。

int main()
{
    // Create a shared pointer with a new object
   std::shared_ptr<exampleClass> p1 = std::make_shared<exampleClass>(60);

   // Now you can safely create a second pointer from your existing one.
   std::shared_ptr<exampleClass> p2 = p1;
   p1->print();
   p2->print();
}

【讨论】:

    【解决方案2】:

    当您从原始指针创建shared_ptr 时,它会获得原始指针的所有权,并且当智能指针超出范围时,它将对拥有的资源调用 delete。将相同的原始指针提供给 2 个不同的 shared_ptrs 会导致双重释放,因为它们都会尝试释放资源。

    如果你需要2个shared_ptrs共享同一个资源,你可以复制第一个:

    int main(){
       exampleClass* object = new exampleClass(60);
    
       std::shared_ptr<exampleClass> p1(object);
       std::shared_ptr<exampleClass> p2 = p1;
    }
    

    这样他们共享资源的所有权(sharaed_ptrs 有一个内部引用计数器,用于跟踪他们中有多少人拥有资源。当您复制 shared_ptr 时,引用计数器会增加。当一个人用完时范围,引用计数器递减。只有当计数器达到零时才会释放资源)因此它只会被释放一次,当最后一个拥有资源的shared_ptr超出范围时。

    通常最好避免明确写出new 并使用make_shared,它会执行分配、为您创建对象并返回拥有它的shared_ptr

    auto object = std::make_shared<exampleClass>(60);
    

    主题中的一些附加高级阅读,与问题不严格相关:

    • 使用make_shared 与手动调用new 时的性能差异:here
    • make_sharedweak_ptrs 和大型对象一起使用的内存影响:here(感谢@Yakk - Adam Nevraumont 提出这个问题,这对我来说是新的:))

    【讨论】:

    • 你可能想提一下make shared weak ptr and large object问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    相关资源
    最近更新 更多