পলিমর্ফিক_অলোকেটর: কখন এবং কেন আমি এটি ব্যবহার করব?


121

এখানে সিপ্রেফারেন্সির ডকুমেন্টেশন , এখানে কাজের খসড়া রয়েছে।

আমাকে অবশ্যই স্বীকার করতে হবে যে আমি বুঝতে পারি নি যে আসল উদ্দেশ্যটি polymorphic_allocatorকখন এবং কেন / কেন / কীভাবে এটি ব্যবহার করা উচিত।
উদাহরণ হিসাবে, pmr::vectorএর নিম্নলিখিত স্বাক্ষর রয়েছে:

namespace pmr {
    template <class T>
    using vector = std::vector<T, polymorphic_allocator<T>>;
}

কি polymorphic_allocatorঅফার? std::pmr::vectorপুরানো ধাঁচের ক্ষেত্রেও অফারটি কী std::vector? আমি এখন কী করতে পারি যে আমি এখন পর্যন্ত করতে পারি নি?
এই বরাদ্দকারীর আসল উদ্দেশ্য কী এবং আমি কখন এটি ব্যবহার করব?


1
তারা allocator<T>সহজাতভাবে কিছু সমস্যা কাটিয়ে উঠার চেষ্টা করে । সুতরাং আপনি যদি ঘন ঘন বরাদ্দ ব্যবহার করেন তবে এর মান দেখতে পাবেন।
edmz

2
প্রাসঙ্গিক কাগজ
edmz

উত্তর:


101

সিপ্রেফারেন্স থেকে পছন্দটি উদ্ধৃতি:

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

"নিয়মিত" বরাদ্দকারীদের সমস্যা হ'ল তারা ধারকটির ধরণ পরিবর্তন করে। আপনি যদি vectorএকটি নির্দিষ্ট বরাদ্দকারী সহ একটি চান , আপনি Allocatorটেমপ্লেট প্যারামিটার ব্যবহার করতে পারেন :

auto my_vector = std::vector<int,my_allocator>();

এখন সমস্যাটি হ'ল এই ভেক্টরটি ভিন্ন বরাদ্দকারী সহ ভেক্টরের মতো একই ধরণের নয়। আপনি এটি কোনও ফাংশনে এটি পাস করতে পারবেন না যার জন্য ডিফল্ট-বরাদ্দকারী ভেক্টর প্রয়োজন, উদাহরণস্বরূপ, বা একই ভেরিয়েবল / পয়েন্টারকে আলাদা বরাদ্দকারী টাইপের সাথে দুটি ভেক্টর বরাদ্দ করুন, যেমন:

auto my_vector = std::vector<int,my_allocator>();
auto my_vector2 = std::vector<int,other_allocator>();
auto vec = my_vector; // ok
vec = my_vector2; // error

পলিমারফিক বরাদ্দকারী হ'ল একক বরাদ্দকারী এমন একটি সদস্য যার সাথে টেমপ্লেট ব্যবস্থাটির পরিবর্তে গতিশীল প্রেরণের মাধ্যমে বরাদ্দকারীর আচরণকে সংজ্ঞায়িত করা যায়। এটি আপনাকে এমন পাত্রে রাখার অনুমতি দেয় যা নির্দিষ্ট, কাস্টমাইজড বরাদ্দ ব্যবহার করে তবে এটি এখনও সাধারণ ধরণের।

বরাদ্দকারীদের আচরণের অনুকূলিতকরণটি বরাদ্দকারীকে একটি দিয়ে দেওয়া হয় std::memory_resource *:

// define allocation behaviour via a custom "memory_resource"
class my_memory_resource : public std::pmr::memory_resource { ... };
my_memory_resource mem_res;
auto my_vector = std::pmr::vector<int>(0, &mem_res);

// define a second memory resource
class other_memory_resource : public std::pmr::memory_resource { ... };
other_memory_resource mem_res_other;
auto my_other_vector = std::pmr::vector<int>(0, &mes_res_other);

auto vec = my_vector; // type is std::pmr::vector<int>
vec = my_other_vector; // this is ok -
      // my_vector and my_other_vector have same type

মূল বাকী ইস্যুটি যেমনটি আমি দেখছি তা হ'ল একটি std::pmr::ধারক এখনও std::ডিফল্ট বরাদ্দকারী ব্যবহার করে সমতুল্য ধারকটির সাথে সামঞ্জস্য নয় । আপনি একটি ইন্টারফেস ডিজাইন করার সময় আপনাকে কিছু সিদ্ধান্ত নিতে হবে যা একটি ধারক নিয়ে কাজ করে:

  • এটি সম্ভবত এমন যে ধারকটি পাস হয়েছে তাতে কাস্টম বরাদ্দের প্রয়োজন হতে পারে?
  • যদি তা হয়, তবে আমি কি কোনও টেম্পলেট প্যারামিটার যুক্ত করব (স্বেচ্ছায় বরাদ্দকারীদের অনুমতি দেওয়ার জন্য) বা আমার পলিমারফিক বরাদ্দক ব্যবহারের আদেশ দিতে হবে?

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

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


2
সুতরাং, std::pmr::ক্লাসগুলির জন্য বাইনারি লেআউট খুব সম্ভবত আলাদা হতে পারে?
ইউরি পিনহলো 16

12
@ ইউরিপিনহলো আপনি যেটি জিজ্ঞাসা করছেন তা যদি আপনি এবং এর reinterpret_castমধ্যে করতে পারেন না । std::vector<X>std::pmr::vector<X>
ডেভম্যাক

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

1
@ ইয়াক্ক-অ্যাডামনেভ্র্যামন্ট "একটি std::pmr::ধারক এখনও std::ডিফল্ট বরাদ্দকারী ব্যবহার করে সমতুল্য পাত্রে" উপযুক্ত নয় । এক থেকে অপরকে সংজ্ঞায়িত কোনও অ্যাসাইনমেন্ট অপারেটর নেই। সন্দেহ হলে, এটি ব্যবহার করে দেখুন: Godbolt.org/z/Q5BKev (কোড ঠিক উপরের মতো নয় কারণ জিসিসি / ক্ল্যাংয়ের একটি "পরীক্ষামূলক" নেমস্পেসে পলিমারফিক বরাদ্দ ক্লাস রয়েছে)।
ডেভম্যাক

1
@ ডেভম্যাক আহ, সুতরাং কোনও template<class OtherA, std::enable_if< A can be constructed from OtherA > vector( vector<T, OtherA>&& )নির্মাণকারী নেই। আমি অনিশ্চিত ছিলাম এবং টিএস-কমপ্লায়েন্ট পিএমআর থাকা একটি সংকলকটি কোথায় পাবেন তা জানতাম না।
ইয়াক্ক - অ্যাডাম নেভ্রামুমন্ট

33

polymorphic_allocatorstd::functionএকটি সরাসরি ফাংশন কল হিসাবে কাস্টম বরাদ্দকারী হয় ।

এটি কেবল আপনাকে ঘোষণার পর্যায়ে কোনও সিদ্ধান্ত না নিয়েই আপনার ধারক সহ একটি বরাদ্দকারী ব্যবহার করতে দেয় which সুতরাং আপনার যদি এমন পরিস্থিতি হয় যেখানে একাধিক বরাদ্দকারী উপযুক্ত হয় তবে আপনি ব্যবহার করতে পারেন polymorphic_allocator

আপনার ইন্টারফেসটি সহজ করার জন্য কোন বরাদ্দকারী ব্যবহার করা হয় তা আপনি লুকিয়ে রাখতে চান বা আপনি হয়ত বিভিন্ন রানটাইম ক্ষেত্রে এটি সরিয়ে নিতে সক্ষম হতে চান।

প্রথমে আপনার কোড দরকার যা একটি বরাদ্দকারী প্রয়োজন, তারপরে আপনাকে পিএমআর ভেক্টর বিবেচনা করার আগে কোনটি ব্যবহৃত হয় তা স্যুপ করতে সক্ষম হবেন।


7

পলিমারফিক বরাদ্দকারীদের একটি অপূর্ণতা polymorphic_allocator<T>::pointerহ'ল সর্বদা ন্যায়সঙ্গত T*। এর অর্থ আপনি অভিনব পয়েন্টার সহ এগুলি ব্যবহার করতে পারবেন না । আপনি যদি একটি জায়গায় উপাদানের ভালো কিছু করতে চান vectorভাগ মেমরি এবং মাধ্যমে তাদের অ্যাক্সেস boost::interprocess::offset_ptrগুলি , আপনি যে জন্য একটি নিয়মিত পুরাতন অ বহুরুপী বরাদ্দকরণ ব্যবহার করতে হবে।

সুতরাং, যদিও পলিমারফিক বরাদ্দকারীরা কোনও ধারকের স্থির ধরণের পরিবর্তন না করেই আপনাকে বরাদ্দের আচরণকে পৃথক করতে দেয় , তারা বরাদ্দ কী তা সীমাবদ্ধ করে


2
এটি একটি মূল পয়েন্ট এবং একটি বড় গুঁড়ো। আর্থার ওডওয়ারের দিকে অর্থবহ অভিনব পয়েন্টারস পেপার এই অঞ্চলটি
ঘুরে দেখেছে

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