এসটিডি :: এর শেয়ারড_পিটার


103

আমি বর্তমানে স্মার্ট পয়েন্টারগুলি কীভাবে ব্যবহার করতে হয় তা শেখার চেষ্টা করছি। তবে কিছু পরীক্ষা-নিরীক্ষা করার সময় আমি নিম্নলিখিত পরিস্থিতিটি আবিষ্কার করেছিলাম যার জন্য আমি কোনও সন্তোষজনক সমাধান খুঁজে পাইনি:

কল্পনা করুন আপনার ক্লাস এ এর ​​একটি বস্তু বি শ্রেণীর (সন্তানের) কোনও সামগ্রীর পিতা বা মাতা হওয়ার বিষয়টি রয়েছে তবে উভয়েরই একে অপরকে জানা উচিত:

class A;
class B;

class A
{
public:
    void addChild(std::shared_ptr<B> child)
    {
        children->push_back(child);

        // How to do pass the pointer correctly?
        // child->setParent(this);  // wrong
        //                  ^^^^
    }

private:        
    std::list<std::shared_ptr<B>> children;
};

class B
{
public:
    setParent(std::shared_ptr<A> parent)
    {
        this->parent = parent;
    };

private:
    std::shared_ptr<A> parent;
};

প্রশ্ন হ'ল ক্লাস এ এর ​​কোনও অবজেক্ট কীভাবে std::shared_ptrনিজের thisসন্তানের কাছে নিজেকে ( ) পাস করতে পারে?

বুস্ট শেয়ার্ড পয়েন্টারগুলির জন্য সমাধান রয়েছে ( একটি পাওয়ার boost::shared_ptrজন্যthis ), তবে কীভাবে এটি std::স্মার্ট পয়েন্টার ব্যবহার করে পরিচালনা করবেন ?


4
অন্য যে কোনও সরঞ্জামের মতো এটি উপযুক্ত হলে এটি ব্যবহার করতে হবে। আপনি যা করছেন তার জন্য স্মার্ট পয়েন্টার ব্যবহার করা তা নয়
ইয়েপিক

একইভাবে উত্সাহ। এখানে দেখুন ।
janchopanza

4
অ্যাবস্ট্রাকশনের সেই স্তরে এটি একটি সমস্যা। আপনি এমনকি জানেন না যে "এটি" গাদা স্মৃতিতে নির্দেশ করে।
ভন ক্যাটো

ভাল, ভাষা না, কিন্তু আপনি না। যতক্ষণ আপনি কোথায় কোথায় তা খোঁজেন, আপনি ভাল থাকবেন।
অ্যালেক্স

উত্তর:


172

std::enable_shared_from_thisএই উদ্দেশ্যে শুধুমাত্র আছে । আপনি এটি থেকে উত্তরাধিকারী এবং আপনি .shared_from_this()ক্লাসের ভিতরে থেকে কল করতে পারেন । এছাড়াও, আপনি এখানে বিজ্ঞপ্তি নির্ভরতা তৈরি করছেন যা রিসোর্স ফাঁস হতে পারে। এটি ব্যবহারের মাধ্যমে সমাধান করা যেতে পারে std::weak_ptr। সুতরাং আপনার কোডটি এর মতো দেখতে পাওয়া যাবে (ধরে নেওয়া বাচ্চারা পিতামাতার অস্তিত্বের উপর নির্ভর করে এবং অন্যভাবে নয়):

class A;
class B;

class A
    : public std::enable_shared_from_this<A>
{
public:
    void addChild(std::shared_ptr<B> child)
    {
        children.push_back(child);

        // like this
        child->setParent(shared_from_this());  // ok
        //               ^^^^^^^^^^^^^^^^^^
    }

private:     
    // note weak_ptr   
    std::list<std::weak_ptr<B>> children;
    //             ^^^^^^^^
};

class B
{
public:
    void setParent(std::shared_ptr<A> parent)
    {
        this->parent = parent;
    }

private:
    std::shared_ptr<A> parent;
};

তবে নোট করুন, কল করার .shared_from_this()জন্য কল পয়েন্টে thisতার মালিকানা থাকা দরকার std::shared_ptr। এর অর্থ হ'ল আপনি আর স্ট্যাকের উপর এ জাতীয় অবজেক্ট তৈরি করতে পারবেন না এবং সাধারণত.shared_from_this() কোনও কনস্ট্রাক্টর বা ডেস্ট্রাক্টরের কাছ থেকে কল করতে পারবেন না ।


4
আপনার ব্যাখ্যা এবং আমার বিজ্ঞপ্তি নির্ভরতা সমস্যা নির্দেশ করার জন্য আপনাকে ধন্যবাদ।
ইকারাস

@ অনুচ্ছেদে আপনার অর্থ কী?
ইউরি কিলোচেক

4
@ উত্সাহক এটি যে, আমার শোধকে ক্ষমা করুন, বরং অর্থহীন ভাগ করা পয়েন্টার। এই কনস্ট্রাক্টরটি পরিচালনা করা অবজেক্ট বা এর ঘাঁটির সদস্যদের পয়েন্টার সহ ব্যবহার করার উদ্দেশ্যে। কোনও ক্ষেত্রে আপনার বক্তব্য কি (আমি দুঃখিত)? এই মালিকানাবিহীন shared_ptrগুলি এই প্রশ্নের সাথে অপ্রাসঙ্গিক। shared_from_thisএর পূর্বশর্তগুলি স্পষ্টভাবে জানিয়েছে যে shared_ptrডেকে যাওয়ার সময় কিছু দ্বারা অবজেক্টটি অবশ্যই মালিকানাধীন হবে (কেবল দেখানো হবে না) ।
ইউরি কিলোচেক

4
@ কজারে মালিকানা shared_ptrকল করার সময় প্রয়োজন হয়, তবে একটি সাধারণ ব্যবহারের ধরণে , অর্থাত্ কিছু shared_ptr<Foo> p(new Foo());, shared_ptrএটি সম্পূর্ণরূপে নির্মিত হওয়ার পরে কেবল অবজেক্টের মালিকানা অনুমান করে। shared_ptrকনস্ট্রাক্টর সূচনা করে thisএটি অ-স্থানীয় (যেমন একটি রেফারেন্স আর্গুমেন্টে) কোথাও সংরক্ষণ করে কন্সট্রাক্টর তৈরি করে তৈরি করা সম্ভব হয় যাতে কনস্ট্রাক্টর সম্পূর্ণ হলে এটি মারা যায় না। তবে এই সংশ্লেষিত দৃশ্যের প্রয়োজনীয়তার সম্ভাবনা কম।
ইউরি কিলোচেক

4
ওপিএস প্রশ্নের উত্তর দেওয়ার জন্য এই প্রতিক্রিয়াটির উপর একটি সুসংগঠন দিয়েছেন। যারা "আরও ভাল উপায়" বা পরামর্শ দেয় না তারা প্রায়শই ভুল হয়। একটি upcountও করেছেন কারণ একটি সমস্যার জন্য আমার এই উত্তরটির প্রয়োজন ছিল। আমি একাধিকবার ব্যবহার করেছি এমন প্রতিমাটি সমস্ত শ্রেণীর দৃষ্টান্তের সম্পূর্ণ তালিকা পাওয়ার জন্য একটি পাত্রে "এটি" লাগিয়ে রাখছে, অর্থাত প্রতিটি ঘটনাকে প্রক্রিয়া করার জন্য ধারকটি হাঁটা। কেন এটি সমস্যাযুক্ত তা দয়া করে নিজেকে ব্যাখ্যা করার চেষ্টা করবেন না। আমি জানি সমস্যাগুলি এবং কীভাবে এগুলি এড়ানো যায়।
rm1948

8

আপনার নকশায় বেশ কয়েকটি সমস্যা রয়েছে, যা স্মার্ট পয়েন্টারগুলির ভুল বোঝাবুঝি থেকে আসে।

স্মার্ট পয়েন্টারগুলি মালিকানা ঘোষণার জন্য ব্যবহৃত হয়। আপনি এই ঘোষণা দিয়ে এই ভেঙে যাচ্ছেন যে বাবা-মা উভয়ই সমস্ত সন্তানের মালিক, তবে প্রতিটি সন্তানেরও তার বাবা-মা রয়েছে। উভয়ই সত্য হতে পারে না।

এছাড়াও, আপনি দুর্বল পয়েন্টারটি ভিতরে ফিরে আসছেন getChild()। এটি করার মাধ্যমে, আপনি ঘোষণা করছেন যে কলকারীকে মালিকানা সম্পর্কে চিন্তা করা উচিত নয়। এখন এটি খুব সীমাবদ্ধ হতে পারে তবে এটি করেও আপনাকে অবশ্যই নিশ্চিত করতে হবে যে কোনও দুর্বল পয়েন্টার এখনও ধরে থাকলেও প্রশ্নে থাকা শিশুটি ধ্বংস হবে না, আপনি যদি স্মার্ট পয়েন্টার ব্যবহার করেন তবে এটি নিজেই বাছাই হয়ে যাবে ।

এবং চূড়ান্ত জিনিস। সাধারণত, আপনি যখন নতুন সত্তা গ্রহণ করছেন, আপনার সাধারণত কাঁচা পয়েন্টার গ্রহণ করা উচিত। পিতামাতার মধ্যে শিশুদের অদলবদলের জন্য স্মার্ট পয়েন্টারটির নিজস্ব অর্থ থাকতে পারে তবে সাধারণ ব্যবহারের জন্য আপনার কাঁচা পয়েন্টার গ্রহণ করা উচিত।


দেখে মনে হচ্ছে স্মার্ট পয়েন্টার সম্পর্কে আমার বোঝার স্পষ্টতা দরকার। এটি নির্দেশ করার জন্য আপনাকে ধন্যবাদ।
আইকারাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.