چرا از std::enable_shared_from_this استفاده می کنیم؟ - هفت خط کد انجمن پرسش و پاسخ برنامه نویسی

چرا از std::enable_shared_from_this استفاده می کنیم؟

0 امتیاز

سلام.

چرا باید از std::enable_shared_from_this استفاده کنیم مگه shared_ptr<MyClass>(this)  اشاره گر هوشمند به هر اشاره گر یا this را برنمی گردونه؟

سوال شده شهریور 2, 1399  بوسیله ی .bahman (امتیاز 137)   3 18 24

2 پاسخ

+2 امتیاز
 
بهترین پاسخ

در برخی از طراحی ها پیش میاد که کلاس های در حال تعامل با کلاس فعلی(D) از شما std::shared_ptr قبول می کنن . خوب شما داخل خود کلاس(S) فقط به this‌ دسترسی دارید و اگر چیزی بخاید بهش پاس بدید قاعدتا اولین چیزی که به ذهن میرسه std::shared<Foo>(this) شاید در نگاه اول درست به نظر بیاد و حتی آدرسی که از این راه بدست میاد  با آدرس مقدار نمونه که از نوع std::shared_ptr این کلاس هستش هم یکی باشه ولی!! این روش undefined behavior هستش به این خاطر که ref count اصلی افزایش نیافته و هنگامی که اشاره گر هوشمند قرار باشه آزاد شه از دو جا میخان آزادش کنن یعنی دو تا ref count‌مجزا .حال چاره چیه ؟ برای اینکه این مشکل تداخل پیش نیاد کلاس مورد نظر را اstd::enable_shared_from_this مشتق کنید با پارامتر جنریک خود کلاس در این صورت با خیال جمع از طریق متد shared_from_this خود کلاس، می تونید اشاره گر هوشمند مربوط به کلاس، با ref count درست، دریافت کنید مثالی هم در زیر براتون قرار دادم  در حالت std::sahred_ptr<this>() با خطا مواجه میشیم.

 

#include <stdio.h>
#include <iostream>
#include <list>
#include <memory>
using  namespace std;
struct S;
struct D{
  void reciver(std::shared_ptr<S> s)  {
      cout << s << endl;
  }
};
struct S: std::enable_shared_from_this<S> {
    std::shared_ptr<S> get_object() {
        return this->shared_from_this();
    };
    void send(std::shared_ptr<D> d){
        d->reciver(std::shared_ptr<S>(this)); //error = wrong method
        d->reciver(get_object()); //OK  = correct method
    }
};


int main() {
    std::shared_ptr<D> ptr_d = std::make_shared<D>();
    std::shared_ptr<S> ptr_s = std::make_shared<S>();
    
    
    cout << ptr_s << endl;
    ptr_s->send(ptr_d);
    
    // ...
}

 

پاسخ داده شده شهریور 2, 1399 بوسیله ی عباس مولایی (امتیاز 2,754)   1 5 13
ویرایش شده شهریور 3, 1399 بوسیله ی مصطفی ساتکی
+1 امتیاز
سلام؛ یه وقتی شما می‌خواید یک Interface C درست کنید از برنامه‌اتون رو اون اشاره‌گر رو به یک پردازهٔ دیگه‌ای ارسالش کنید حالا اگه اون‌ور هم بخواید Ownership‌ همون std::shared_ptr رو بگیرید می‌تونید کلاستون رو از std::enable_shared_from_this ارث‌بری کنید تا مالکیّت رو داخل کلاستون داشته باشید.

به‌طور خلاصه: با ارث‌بری از std::enable_shared_from_this شما می‌تونید یک std::shared_ptr داخل کلاستون با References counter داشته باشید. البته بیشترین استفاده‌ای که از این داشتم این بوده که با استفاده از یک Interface C من یک اشاره‌گر از کلاس به یک پردازهٔ دیگه ارسال می‌کردم و اون‌جا نیاز داشتم که References counter رو هم داشته باشم برای std::shared_ptr. امّا بعدها کلاً از boost::dll استفاده کردم.
پاسخ داده شده شهریور 2, 1399 بوسیله ی mg_ramezani (امتیاز 727)   1 1 12
ویرایش شده شهریور 2, 1399 بوسیله ی mg_ramezani
...