指向 object 显式创建 object 的智能指针

Smart pointers to an object explicitly created object

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

我创建了一个class如下-

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,因为两个指针都用于相同的 object?

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

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

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();
}

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

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

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,它会进行分配,为您创建对象,并且 returns 拥有一个 shared_ptr它:

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

主题中的一些额外的高级阅读,与问题没有严格关系:

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