কাস্টম বরাদ্দকারী দ্বারা বরাদ্দকৃত একটি শেয়ার্ড_প্টারের ডিলেটর মেমোরিতে সঞ্চয় করা আছে?


22

আমি বলার shared_ptrএকটি কাস্টম বরাদ্দকরণ সঙ্গে এবং একটি কাস্টম deleter।

আমি স্ট্যান্ডার্ডে এমন কিছু খুঁজে পাচ্ছি না যেখানে মুছে ফেলা হবে কোথায় তা নিয়ে কথা বলবে: এটি কাস্টম বরাদ্দকারী মুছে ফেলার স্মৃতির জন্য ব্যবহৃত হবে এবং এটি বলে না যে এটি হবে না

এটি কি অনির্দিষ্ট বা আমি কেবল কিছু মিস করছি?

উত্তর:


11

সি ++ 11 এ ব্যবহার.সামার্ট.আর.শার্ড.কনস্ট / 9:

ইফেক্টস: একটি শেয়ার্ড_পিটার অবজেক্ট তৈরি করে যা অবজেক্ট পি এবং মুছে ফেলার মালিক d। দ্বিতীয় এবং চতুর্থ নির্মাতারা অভ্যন্তরীণ ব্যবহারের জন্য মেমরি বরাদ্দ করতে একটি অনুলিপি ব্যবহার করবেন।

দ্বিতীয় এবং চতুর্থ নির্মাতাদের এই প্রোটোটাইপ রয়েছে:

template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template<class D, class A> shared_ptr(nullptr_t p, D d, A a);

সর্বশেষ খসড়াটিতে, ব্যবহার.সাম্পার্ট.শায়ারড.কম / 10 আমাদের উদ্দেশ্যে সমান:

ইফেক্টস: একটি শেয়ার্ড_পিটার অবজেক্ট তৈরি করে যা অবজেক্ট পি এবং মুছে ফেলার মালিক d। যখন টি অ্যারে টাইপ নয়, প্রথম এবং দ্বিতীয় কনস্ট্রাক্টরগুলি ভাগ করে_ফ্রমে_ পি সহ সক্ষম করে। দ্বিতীয় এবং চতুর্থ নির্মাতারা অভ্যন্তরীণ ব্যবহারের জন্য মেমরি বরাদ্দ করতে একটি অনুলিপি ব্যবহার করবেন। যদি একটি ব্যতিক্রম নিক্ষেপ করা হয়, d (পি) বলা হয়।

সুতরাং বরাদ্দকারী ব্যবহৃত হয় যদি বরাদ্দ মেমরিতে এটি বরাদ্দ করার প্রয়োজন হয়। বর্তমান মান এবং প্রাসঙ্গিক ত্রুটি প্রতিবেদনের ভিত্তিতে বরাদ্দ বাধ্যতামূলক নয় তবে কমিটি ধরে নিয়েছে।

  • যদিও এর ইন্টারফেসটি এমন shared_ptrএকটি বাস্তবায়নের অনুমতি দেয় যেখানে কখনই নিয়ন্ত্রণ ব্লক এবং সমস্ত থাকে না shared_ptrএবং weak_ptrএগুলি একটি লিঙ্কযুক্ত তালিকায় রাখা হয়, বাস্তবে তেমন কোনও বাস্তবায়ন হয় না। অতিরিক্ত হিসাবে, উদাহরণস্বরূপ, use_countভাগ করে নেওয়া হয়েছে তা ধরে ধরে শব্দটির সংশোধন করা হয়েছে ।

  • মুছে ফেলার জন্য কেবল গঠনমূলক পদক্ষেপ নেওয়া প্রয়োজন। সুতরাং, এটিতে বেশ কয়েকটি অনুলিপি থাকা সম্ভব নয় shared_ptr

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

প্রাসঙ্গিক ডিআরএস আমি পেয়েছি: 545 , 575 , 2434 (যা স্বীকৃতি দেয় যে সমস্ত বাস্তবায়ন একটি নিয়ন্ত্রণ ব্লক ব্যবহার করছে এবং এটি বোঝায় যে মাল্টি-থ্রেডিং সীমাবদ্ধতা কিছুটা এটিকে নির্দেশ দেয়), 2802 (যার প্রয়োজন মুছে ফেলা কেবল গঠনমূলক পদক্ষেপে চলে যায় এবং ফলস্বরূপ বাস্তবায়নে বাধা দেয় যেখানে মুছে ফেলা বেশ কয়েকটি shared_ptrএর মধ্যে অনুলিপি করা হয় )।


2
"অভ্যন্তরীণ ব্যবহারের জন্য মেমরি বরাদ্দ করতে" যদি বাস্তবায়নটি অভ্যন্তরীণ ব্যবহারের জন্য মেমরি বরাদ্দ না করে তবে কি হবে? এটি কোনও সদস্যকে ব্যবহার করতে পারে।
এলএফ

1
@ এলএফ এটি করতে পারে না, ইন্টারফেসটি এটির জন্য অনুমতি দেয় না।
এপ্রোগ্রামার

তাত্ত্বিকভাবে, এটি এখনও কিছু ধরণের "ছোট মুছক অপ্টিমাইজেশন" ব্যবহার করতে পারে, তাই না?
এলএফ

অদ্ভুতরূপটি হ'ল আমি সেই স্মৃতিটিকে হ্রাসa করতে একই বরাদ্দকারী (অনুলিপি ) ব্যবহার সম্পর্কে কিছুই খুঁজে পাচ্ছি না । যা সেই অনুলিপিটির কিছু সঞ্চয়স্থান বোঝায় । [Use.smartptr.shared.dest] এ সম্পর্কে কোনও তথ্য নেই। a
ড্যানিয়েল ল্যাঙ্গার

1
@ ড্যানিয়েলসরেইনস্টেটমোনিকা, আমি অবাক হয়েছি যদি Use.smartptr.shared / 1 এ: "শেয়ারড_সিপিআর শ্রেণি টেম্পলেটটি সাধারণত নতুন মাধ্যমে প্রাপ্ত হয়। শেয়ার্ড_পিটার ভাগ করে নেওয়া মালিকানার শব্দার্থক প্রয়োগ করে; পয়েন্টারের শেষের মালিক অবজেক্টটি ধ্বংস করার জন্য দায়ী, বা অন্যথায় সঞ্চিত পয়েন্টারের সাথে যুক্ত রিসোর্সগুলি প্রকাশ করা হচ্ছে। মুক্তি সঞ্চিত পয়েন্টার সঙ্গে যুক্ত সম্পদ যে জন্য উদ্দেশ্যে নয়। শেষ দুর্বল পয়েন্টার মোছা না হওয়া পর্যন্ত নিয়ন্ত্রণ ব্লকটিও বেঁচে থাকবে।
এপ্রোগ্রামার

4

এসটিডি থেকে :: শেয়ারড_পিটিআর আমরা আছে:

কন্ট্রোল ব্লক একটি গতিশীল-বরাদ্দ করা বস্তু যা ধারণ করে:

  • হয় পরিচালিত বস্তু বা নিজেই পরিচালিত অবজেক্টের পয়েন্টার;
  • মুছে ফেলা (টাইপ মোছা);
  • বরাদ্দকারী (টাইপ-মুছে ফেলা);
  • পরিচালিত অবজেক্টের মালিকানাধীন শেয়ারড_টার সংখ্যা;
  • দুর্বল_প্টারের সংখ্যা যা পরিচালিত অবজেক্টকে উল্লেখ করে।

এবং এসটিডি থেকে :: বরাদ্দ_ভাগ শেয়ার করা আমরা পাই:

template< class T, class Alloc, class... Args >
shared_ptr<T> allocate_shared( const Alloc& alloc, Args&&... args );

শেয়ার টাইপ পয়েন্টার এবং টি অবজেক্টের নিয়ন্ত্রণ ব্লক উভয়ের জন্য একটি বরাদ্দ ব্যবহার করার জন্য একটি টাইপ টি এর অবজেক্ট তৈরি করে এবং এটি একটি এসটিডি :: শেয়ারড_পিটার [...] এ মোড়ানো করে ।

সুতরাং দেখে মনে হচ্ছে যে স্টাড :: বরাদ্দ_ ভাগ করে নেওয়া উচিত deleterআপনার সাথে বরাদ্দ Alloc

সম্পাদনা করুন: এবং n4810§20.11.3.6 থেকে তৈরি [ইউজার.সাম্পার্ট.শায়ারড। ক্রিয়েট]

1 সাধারণ প্রয়োজনীয়তা যে সব ক্ষেত্রে প্রযোজ্য make_shared, allocate_shared, make_shared_default_init, এবংallocate_shared_default_init overloads, যদি না অন্যথায় নিদিষ্ট, নীচের বর্ণনা করা হয়।

[...]

Re টি মন্তব্য: ().১) - বাস্তবায়নের ক্ষেত্রে একের বেশি মেমরি বরাদ্দ করা উচিত নয়। [দ্রষ্টব্য: এটি হস্তক্ষেপকারী স্মার্ট পয়েন্টারের সমতুল্য দক্ষতা সরবরাহ করে। অন্তর্ভুক্ত নোট]

[সমস্ত আমার উপর জোর দিন]

সুতরাং স্ট্যান্ডার্ড বলছে যে নিয়ন্ত্রণ ব্লক ব্যবহার করা std::allocate_shared উচিতAlloc


1
আমি cppreferences দ্বারা দুঃখিত একটি আদর্শ পাঠ্য নয়। এটি একটি দুর্দান্ত সংস্থান, তবে ভাষা-আইনজীবী প্রশ্নগুলির জন্য প্রয়োজনীয় নয় ।
গল্পগ্রাহক - আনস্ল্যান্ডার মনিকা

@ স্টোরি টেলার-আনস্ল্যান্ডারমোনিকা সম্পূর্ণরূপে সম্মত হন - সর্বশেষতম স্ট্যান্ডার্ডটি দেখেছেন এবং এমন কিছু খুঁজে পেলেন না যা cppreferences দিয়ে গেছে।
পল ইভান্স

@ পলএভানস, ইয়েল.ইস.সি
++

পাওয়া n4810এবং আপডেট উত্তর।
পল ইভান্স

1
যাইহোক, এটি কথা বলছেন make_shared, নির্মাতারা নিজেরাই নয়। তবুও, আমি ছোট মুছে ফেলার জন্য সদস্য ব্যবহার করতে পারি।
এলএফ

3

আমি বিশ্বাস করি এটি অনির্ধারিত।

এখানে প্রাসঙ্গিক কন্সট্রাক্টরের স্পেসিফিকেশন: [Use.smartptr.shared.const] / 10

template<class Y, class D> shared_ptr(Y* p, D d);
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template <class D> shared_ptr(nullptr_t p, D d);
template <class D, class A> shared_ptr(nullptr_t p, D d, A a);

প্রভাবগুলি:shared_­ptr এমন একটি বস্তু তৈরি করে যা অবজেক্ট pএবং মুছকটির মালিক d। যখন Tএকটি অ্যারের টাইপ নয়, প্রথম এবং দ্বিতীয় কনস্ট্রাকটর সক্ষম shared_­from_­thisসঙ্গে p। দ্বিতীয় এবং চতুর্থ নির্মাতারা অভ্যন্তরীণ ব্যবহারের জন্য মেমরি বরাদ্দ করতে একটি অনুলিপি aব্যবহার করবেন । যদি কোনও ব্যতিক্রম নিক্ষেপ করা d(p)হয় তবে তাকে ডাকা হয়।

এখন, আমার ব্যাখ্যাটি হ'ল বাস্তবায়নের অভ্যন্তরীণ ব্যবহারের জন্য যখন মেমরির প্রয়োজন হয় তখন এটি ব্যবহার করে তা করে a । এর অর্থ এই নয় যে বাস্তবায়নের সমস্ত কিছু স্থাপনের জন্য এই মেমরিটি ব্যবহার করতে হবে। উদাহরণস্বরূপ, ধরুন যে এই অদ্ভুত বাস্তবায়ন রয়েছে:

template <typename T>
class shared_ptr : /* ... */ {
    // ...
    std::aligned_storage<16> _Small_deleter;
    // ...
public:
    // ...
    template <class _D, class _A>
    shared_ptr(nullptr_t, _D __d, _A __a) // for example
        : _Allocator_base{__a}
    {
        if constexpr (sizeof(_D) <= 16)
            _Construct_at(&_Small_deleter, std::move(__d));
        else
            // use 'a' to allocate storage for the deleter
    }
// ...
};

এই প্রয়োগটি কি " aঅভ্যন্তরীণ ব্যবহারের জন্য মেমরি বরাদ্দ করতে একটি অনুলিপি ব্যবহার করে"? হ্যাঁ এটা করে. এটি কখনও ব্যবহার না করে স্মৃতি বরাদ্দ করে a। এই নিখুঁত বাস্তবায়নে অনেক সমস্যা রয়েছে, তবে আসুন আমরা বলি যে এটি সরল ক্ষেত্রে কেবল বরাদ্দকারীদের ব্যবহার করতে স্যুইচ করে, যেখানে shared_ptrপয়েন্টার থেকে সরাসরি নির্মিত হয় এবং এটি কখনই অনুলিপি করা বা সরানো বা অন্যথায় উল্লেখ করা হয় না এবং অন্য কোনও জটিলতা নেই। মুল বক্তব্যটি হ'ল, আমরা বৈধ বাস্তবায়নটি কল্পনা করতে ব্যর্থ হয়েছি বলে নিজেই প্রমাণ করে না যে এটি তাত্ত্বিকভাবে বিদ্যমান থাকতে পারে না। আমি বলছি না যে এই জাতীয় বাস্তবায়ন প্রকৃত বিশ্বে পাওয়া যাবে, কেবল এটি মানকটিকে সক্রিয়ভাবে নিষিদ্ধ করছে বলে মনে হয় না।


shared_ptrছোট ধরণের আইএমও আপনার স্ট্যাকের জন্য মেমরি বরাদ্দ করে। এবং তাই স্ট্যান্ডার্ড প্রয়োজনীয়তা পূরণ করে না
বার্টপ

1
@ বার্টপ এটি স্ট্যাকের কোনও মেমরি "বরাদ্দ" করে না। _সামলার_দেহকর্তা নিঃশর্তভাবে একটি ভাগ করা_সেপ্টারের উপস্থাপনার অংশ। এই স্পেসে কনস্ট্রাক্টরকে কল করার অর্থ কিছু বরাদ্দ নয়। অন্যথায়, এমনকি কন্ট্রোল ব্লকের একটি পয়েন্টার ধরে রাখা "মেমরি বরাদ্দ" হিসাবে গণনা করে, তাই না? :-)
এলএফ

তবে মুছে ফেলার জন্য অনুলিপিযোগ্য হওয়ার দরকার নেই, তবে এটি কীভাবে কাজ করবে?
নিকল বোলাস

@ নিকলবোলাস উম্ম ... ব্যবহার করুন std::move(__d)এবং allocateঅনুলিপি প্রয়োজন হলে ফিরে যান ।
এলএফ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.