শেয়ার করা_পাত্র যাদু :)


91

মিঃ লিডস্ট্রাম এবং আমার একটি যুক্তি ছিল :)

মিঃ লিডস্ট্রমের দাবী একটি কনস্ট্রাক্টের shared_ptr<Base> p(new Derived);জন্য ভার্চুয়াল ডেস্ট্রাক্টর থাকতে বেসের প্রয়োজন হয় না:

আর্মেন ​​সিরুনিয়ান : "সত্যিই? শেয়ার্ড_প্টার কি সঠিকভাবে পরিষ্কার হয়ে যাবে? আপনি কি এই ক্ষেত্রে কীভাবে এই প্রভাবটি কার্যকর করতে পারবেন তা প্রদর্শন করতে পারেন?"

ড্যানিয়েল লিডস্ট্রোম : " শেয়ারড_প্টর কংক্রিটের উদাহরণটি মুছতে তার নিজস্ব ডেস্ট্রাক্টর ব্যবহার করে This এটি সি ++ সম্প্রদায়ের মধ্যে আরআইআই নামে পরিচিত My সমস্ত পরিস্থিতিতে RAII। "

আর্মেন ​​তিরুনিয়ান : "আমি আরআইআই সম্পর্কে জানি, এবং আমি আরও জানি যে অবশেষে ভাগ করা_পিটার ডেস্ট্রাক্টর পিএন 0 এ পৌঁছালে সঞ্চিত px মুছে ফেলতে পারে তবে পিএক্স যদি স্ট্যাটিক টাইপ পয়েন্টার Baseএবং ডায়নামিক টাইপ পয়েন্টার থাকে Derivedতবে যদি Baseভার্চুয়াল ডেস্ট্রাক্টর না থাকে এটি অপরিবর্তিত আচরণের ফলাফল হবে I আমি ভুল হলে আমাকে সংশোধন করুন ""

ড্যানিয়েল লিডস্ট্রোম : " শেয়ার্ড_পটার স্ট্যাটিক টাইপটি কংক্রিটের বিষয়টি জানে knows আমি এটি এটির নির্মাতায় পাস করার পর থেকে এটি জানে! কিছুটা যাদু বলে মনে হয় তবে আমি আপনাকে নিশ্চিত করতে পারি যে এটি নকশা এবং অত্যন্ত সুন্দর।"

সুতরাং, আমাদের বিচার করুন। ভার্চুয়াল ডেস্ট্রাক্টর পলিমারফিক ক্লাস প্রয়োজন না করে শেয়ারড_পিটার বাস্তবায়ন কীভাবে সম্ভব (যদি তা হয়) ? আগাম ধন্যবাদ


4
আপনি মূল থ্রেডের সাথে লিঙ্ক করতে পারতেন ।
দারিন দিমিত্রভ

8
আরেকটি মজার বিষয় হল shared_ptr<void> p(new Derived)এছাড়াও ধ্বংস করবে Derived, এটা বিনাশকারী দ্বারা বস্তুর নির্বিশেষে যদি তা না হয় virtualবা না।
ডাল

7
একটি প্রশ্ন জিজ্ঞাসা করার দুর্দান্ত উপায় :)
রুবেনভবি

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

6
RAII নয়, বরং এটি ধ্বংসকারীকে টাইপ-মুছে ফেলে। আপনাকে সাবধানতা অবলম্বন করতে হবে, কারণ সঠিক কাজটি shared_ptr<T>( (T*)new U() )কোথায় struct U:Tকরবে না (এবং এটি পরোক্ষভাবে সহজেই করা যেতে পারে, যেমন একটি ফাংশন যা লাগে T*এবং পাস হয় U*)
ইয়াক্ক - অ্যাডাম নেভ্রামামন্ট

উত্তর:


74

হ্যাঁ, শেয়ারড_পিটারটি সেভাবে বাস্তবায়ন করা সম্ভব। বুস্ট দেয় এবং সি ++ 11 স্ট্যান্ডার্ডের জন্যও এই আচরণটি প্রয়োজন। একটি যুক্ত নমনীয়তা হিসাবে ভাগ করা_পিটার কেবল একটি রেফারেন্স কাউন্টার ছাড়াই বেশি পরিচালনা করে। একটি তথাকথিত মুছে ফেলা সাধারণত একই মেমরি ব্লকে রাখা হয় যাতে রেফারেন্স কাউন্টারগুলিও থাকে। তবে মজাদার অংশটি হ'ল এই মুছে ফেলার ধরণটি শেয়ারড_পিটার টাইপের অংশ নয়। এটিকে "টাইপ ইরেজর" বলা হয় এবং মূলত একই কৌশলটি "পলিমারফিক ফাংশন" বুস্ট :: ফাংশন বা স্ট্যান্ড :: ফাংশন বাস্তব প্রকৃতির ফ্যান্টারের আড়াল করার জন্য প্রয়োগ করার জন্য ব্যবহৃত হয়। আপনার উদাহরণটি কাজ করতে আমাদের একটি টেম্প্লেটেড কনস্ট্রাক্টর দরকার:

template<class T>
class shared_ptr
{
public:
   ...
   template<class Y>
   explicit shared_ptr(Y* p);
   ...
};

সুতরাং, আপনি যদি এটি আপনার ক্লাস বেস এবং ডাইরাইভ করে ব্যবহার করেন ...

class Base {};
class Derived : public Base {};

int main() {
   shared_ptr<Base> sp (new Derived);
}

... ওয়াই = ডেরিভের সাহায্যে টেম্প্লেটেড কনস্ট্রাক্টর শেয়ারড_পিটার অবজেক্টটি তৈরি করতে ব্যবহৃত হয়। কনস্ট্রাক্টরের পক্ষে উপযুক্ত মুছে ফেলা অবজেক্ট এবং রেফারেন্স কাউন্টার তৈরি করার এবং ডেটা সদস্য হিসাবে এই নিয়ন্ত্রণ ব্লকের একটি পয়েন্টার সঞ্চয় করার সুযোগ রয়েছে। যদি রেফারেন্স কাউন্টার শূন্যে পৌঁছে যায়, তবে পূর্বে তৈরি এবং উত্পন্ন সচেতন মুছে ফেলা অবজেক্টটি নিষ্পত্তি করার জন্য ব্যবহৃত হবে।

সি ++ 11 স্ট্যান্ডার্ডটির এই নির্মাতা সম্পর্কে (20.7.2.2.1) সম্পর্কে নিম্নলিখিত কথা রয়েছে:

প্রয়োজনীয়: p অবশ্যই রূপান্তরযোগ্য হতে হবে T*Yএকটি সম্পূর্ণ ধরণের হতে হবে। অভিব্যক্তিটি delete pসুগঠিত হবে, ভাল সংজ্ঞাযুক্ত আচরণ করবে এবং ব্যতিক্রম ছোঁড়াবে না।

প্রভাব: পয়েন্টারের মালিক এমন একটি shared_ptrবস্তু তৈরি করে p

এবং ধ্বংসকারীদের জন্য (20.7.2.2.2):

এফেক্টস: যদি *thisহয় খালি অন্যের সঙ্গে বা শেয়ারের মালিকানা shared_ptrউদাহরণস্বরূপ ( use_count() > 1), কোন পার্শ্ব প্রতিক্রিয়া আছে। অন্যথায়, যদি *thisকোনও অবজেক্ট pএবং একটি মুছে ফেলার মালিক থাকে d, d(p)তাকে ডাকা হয়। অন্যথায়, যদি *thisপয়েন্টারের মালিক হয় p, এবং delete pতাকে ডাকা হয়।

(গা bold় ফন্ট ব্যবহার করে জোর দেওয়া আমার))


the upcoming standard also requires this behaviour: (ক) কোন মানদণ্ড এবং (খ) আপনি দয়া করে একটি রেফারেন্স সরবরাহ করতে পারেন (মানটির)?
কেভিনার্পে

আমি কেবলমাত্র সেলিবিটজের উত্তরে একটি মন্তব্য যুক্ত করতে চাই যেহেতু আমার কাছে পর্যাপ্ত পয়েন্ট নেই add a comment। আইএমও, এটি এর Boost does thisচেয়ে বেশি the Standard requires। আমি মনে করি না যে স্ট্যান্ডার্ডটির যা প্রয়োজন তা আমি বুঝতে পারি। @Sellibitze এর উদাহরণ সম্পর্কে কথা বলা shared_ptr<Base> sp (new Derived);, প্রয়োজন এর constructorমাত্র জন্য অনুরোধ delete Derivedভাল হচ্ছে সংজ্ঞায়িত করা হয় এবং ভাল গঠন করে। এর স্পেসিফিকেশনের জন্য destructor, একটিও রয়েছে p, তবে আমি মনে করি না যে এটির pস্পেসিফিকেশনটিতে এর উল্লেখ রয়েছে constructor
লুজুন ওয়েং

28

যখন শেয়ারড_পিটার তৈরি করা হয় তখন এটি নিজের মধ্যে একটি মুছে ফেলা বস্তু সঞ্চয় করে। যখন ভাগ করা_পিটার পয়েন্ট রিসোর্সটি মুক্ত করতে চলেছে তখন এই অবজেক্টটি ডাকা হয়। যেহেতু আপনি কীভাবে নির্মাণের পর্যায়ে সংস্থানটি ধ্বংস করতে জানেন আপনি অসম্পূর্ণ প্রকারের সাথে শেয়ারড_পিটার ব্যবহার করতে পারেন। যে কেউ শেয়ারড_পিটার তৈরি করেছে সেগুলি সেখানে একটি সঠিক মুছক সংরক্ষণ করে।

উদাহরণস্বরূপ, আপনি একটি কাস্টম মোছা তৈরি করতে পারেন:

void DeleteDerived(Derived* d) { delete d; } // EDIT: no conversion needed.

shared_ptr<Base> p(new Derived, DeleteDerived);

পয়েন্টযুক্ত অবজেক্টটি ধ্বংস করতে ডিলিটডেরাইভকে কল করবে। বাস্তবায়ন এটি স্বয়ংক্রিয়ভাবে করে।


4
অসম্পূর্ণ প্রকার সম্পর্কে মন্তব্যটির জন্য +1, shared_ptrকোনও গুণ হিসাবে ব্যবহার করার সময় খুব সহজ ।
ম্যাথিউ এম।

16

কেবল,

shared_ptr কনস্ট্রাক্টর দ্বারা তৈরি করা বিশেষ মুছক ফাংশন ব্যবহার করে যা সর্বদা প্রদত্ত বস্তুর ডেস্ট্রাক্টর ব্যবহার করে এবং বেসের ডেস্ট্রাক্টর নয়, এটি টেমপ্লেট মেটা প্রোগ্রামিং সহ কিছুটা কাজ করে তবে এটি কাজ করে।

এরকম কিছু

template<typename SomeType>
shared_ptr(SomeType *p)
{
   this->destroyer = destroyer_function<SomeType>(p);
   ...
}

4
হুম ... আকর্ষণীয়, আমি এটি বিশ্বাস করতে শুরু করছি :)
আর্মেন ​​সিরুনিয়ান

4
@ আরমান সিরুনিয়ান আপনার আলোচনা শুরু করার আগে ভাগ করা_প্টারের নকশা বিবরণটি দেখে নেওয়া উচিত ছিল। এই 'মুছে ফেলা ক্যাপচার' শেয়ার্ড_পিটরের অন্যতম প্রয়োজনীয় বৈশিষ্ট্য ...
পল

6
@ পল_71১: আমি আপনার সাথে একমত অন্যদিকে আমি বিশ্বাস করি যে এই আলোচনাটি কেবল আমার জন্যই নয়, এমন অন্যান্য লোকদের জন্যও যারা এই অংশটি শেয়ারড_পিটার সম্পর্কে জানে না for সুতরাং আমি অনুমান করি যেভাবেই এই থ্রেডটি শুরু করা কোনও
মহাপাপ নয়

4
@ আর্মেন ​​অবশ্যই না। পরিবর্তে, আপনি শেয়ারড_সিপিআর <টি> এর এটি অত্যন্ত গুরুত্বপূর্ণ বৈশিষ্ট্যটির দিকে ইঙ্গিত করার ক্ষেত্রে একটি ভাল কাজ করেছেন যা অভিজ্ঞ সি ++ বিকাশকারীদের দ্বারা প্রায়শই তদারকি করা হয়।
পল মিশালিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.