কেন ভেক্টর <বিউল> একটি এসটিএল ধারক নয়?


103

স্কট মায়ার্স এর বই এর আইটেম 18 কার্যকর STL: 50 নির্দিষ্ট উপায় স্ট্যান্ডার্ড টেমপ্লেট লাইব্রেরী আপনার ব্যবহার উন্নত করতে এড়াতে বলেছেন vector <bool>কেননা এতে একটি STL ধারক নয় এবং এটি সত্যিই না রাখা boolগুলি।

নিম্নলিখিত কোড:

vector <bool> v; 
bool *pb =&v[0];

সংকলন করবে না, এসটিএল পাত্রে প্রয়োজনীয়তা লঙ্ঘন করছে।

ত্রুটি:

cannot convert 'std::vector<bool>::reference* {aka std::_Bit_reference*}' to 'bool*' in initialization

vector<T>::operator []রিটার্ন টাইপ হওয়ার কথা T&, তবে এটি কেন একটি বিশেষ ক্ষেত্রে vector<bool>?

আসলে কী থাকে vector<bool>?

আইটেমটি আরও বলেছে:

deque<bool> v; // is a STL container and it really contains bools

এটি বিকল্প হিসাবে ব্যবহার করা যেতে পারে vector<bool>?

কেউ দয়া করে এটি ব্যাখ্যা করতে পারেন?


22
এটি সি ++ 98 এ ডিজাইনের ভুল ছিল, এখন এটি সামঞ্জস্যের জন্য ধরে রাখা হয়েছে।
Oktalist

8
@ জি-মাকুলিক, এটি নয় যে এটির ব্যবহারটি সংকলন করবে না, যে boolউপাদানটির নিজস্ব ঠিকানা নেই সেহেতু আপনি কোনও উপাদানটির ঠিকানা পয়েন্টারে সংরক্ষণ করতে পারবেন না ।
ক্রিস

4
সম্ভবত এটি সহায়তা করবে: স্ট্যাকওভারফ্লো
ক্রিস

4
@ জি-মাকুলিক std::vector<bool> v;সংকলন করবে। &v[0](একটি অস্থায়ী ঠিকানা গ্রহণ) করবে না।
Oktalist

4
vector<bool>একটি খারাপ প্রতিনিধির রয়েছে কিন্তু না সম্পূর্ণরূপে যথার্থই তাই: isocpp.org/blog/2012/11/on-vectorbool
TemplateRex

উত্তর:


120

স্পেস-অপ্টিমাইজেশনের কারণে, সি ++ স্ট্যান্ডার্ড (সি ++ 98 এর মতো ফিরে) স্পষ্টভাবে vector<bool>একটি বিশেষ স্ট্যান্ডার্ড ধারক হিসাবে ডাকে যেখানে প্রতিটি বুল একটি সাধারণ বুল হিসাবে এক বাইটের পরিবর্তে কেবলমাত্র একটি বিট স্পেস ব্যবহার করে (এক ধরণের বাস্তবায়ন করে) "গতিশীল বিটসেট")। এই অপ্টিমাইজেশনের বিনিময়ে এটি একটি সাধারণ স্ট্যান্ডার্ড ধারকটির সমস্ত ক্ষমতা এবং ইন্টারফেস সরবরাহ করে না।

এই ক্ষেত্রে, যেহেতু আপনি একটি বাইটের মধ্যে কিছুটা ঠিকানা নিতে পারবেন না, তাই বিষয়গুলি যেমন operator[]ফিরে আসতে পারে না bool&তবে পরিবর্তে একটি প্রক্সি অবজেক্ট ফেরত দেয় যা নির্দিষ্ট বিটটিকে প্রশ্নবিদ্ধ করতে দেয়। যেহেতু এই প্রক্সি অবজেক্টটি একটি নয় bool&, আপনি bool*কোনও "নরমাল" ধারকটিতে এমন কোনও অপারেটর কল করার ফলাফলের সাথে তার ঠিকানাটিকে এমনটির মতো বরাদ্দ করতে পারবেন না । পরিবর্তে এর অর্থ এটি bool *pb =&v[0];বৈধ কোড নয়।

অন্যদিকে dequeএমন কোনও বিশেষায়িত কল নেই যা প্রতিটি বুল একটি বাইট নেয় এবং আপনি যে মানটি দিয়েছিলেন তার ঠিকানাটি নিতে পারেন operator[]

পরিশেষে নোট করুন যে এমএস স্ট্যান্ডার্ড লাইব্রেরি বাস্তবায়ন (তর্কযুক্ত) সাবোকটিমাল যাতে এটি ডেকসের জন্য একটি ছোট আকারের আকার ব্যবহার করে, যার অর্থ বিকল্প হিসাবে ডেক ব্যবহার করা সর্বদা সঠিক উত্তর নয়।


4
আমাদের কি অন্য কোনও ডেটা টাইপ রয়েছে যার জন্য অন্য কোনও এসটিএল ধারক বিশেষায়িত বা স্পষ্টভাবে বলা হয়?
P0W

4
এটি কি সি ++ ১১ তম :: অ্যারে <বিউল> এর জন্য প্রযোজ্য?
সেরজিও বাসুরকো

4
@ চকলেপ্লান্ট নং, std::arrayএটি কেবলমাত্র T[n]কিছু সহায়ক সহায়ক ফাংশন size(), অনুলিপি / মুভ শব্দার্থক শব্দগুলির একটি কাঁচা অ্যারের চারপাশে একটি টেম্প্লেটেড মোড়ক এবং এটির এসটিএল-সামঞ্জস্যপূর্ণ করার জন্য পুনরাবৃত্তি যুক্ত করা হয়েছে - এবং (ধন্যবাদ) এটি তার নিজস্ব নীতিগুলি লঙ্ঘন করে না (আমার নোট এগুলির সংশয় :) 'এর জন্য' বিশেষজ্ঞ bool'।
আন্ডারস্কোর_ডে

কেবল একটি নিট পিক - মাপের (বুল) বাইট নয়। stackoverflow.com/questions/4897844/…
উরি রাজ

30

vector<bool>মানের জন্য মাত্র একটি বিট ব্যবহার করে সংকুচিত আকারে বুলিয়ান মান রয়েছে (এবং এটি 8 নয় কীভাবে বুল [] অ্যারেগুলি করে)। সি ++ তে কিছুটা রেফারেন্স পাওয়া সম্ভব নয়, সুতরাং একটি বিশেষ সহায়ক সাহায্যকারী টাইপ রয়েছে, "বিট রেফারেন্স", যা আপনাকে কিছুটা মেমরির জন্য একটি ইন্টারফেস সরবরাহ করে এবং আপনাকে স্ট্যান্ডার্ড অপারেটর এবং ক্যাসেট ব্যবহার করতে দেয়।


4
@ প্রশান্তস্রীবাস্তব বিশেষায়িত deque<bool>নয় তাই এটি আক্ষরিক অর্থেই কেবল একটি উপযুক্ত হোল্ডিং বুলস।
কনরাড রুডল্ফ

@ প্রশান্তশ্রীবাস্তব vector<bool>একটি নির্দিষ্ট টেম্পলেট বাস্তবায়ন করেছেন। আমার ধারণা, অন্যান্য এসটিএল পাত্রে যেমন deque<bool>, না, তাই তারা অন্য ধরণের মতো বুল-গুলি ধরে।
ইভান স্মারনভ

এখানে মরিচায় অনুরূপ একটি প্রশ্ন জিজ্ঞাসা করা হচ্ছে যেখানে তারা একক বিট বুলিয়ানস স্ট্যাকওভারফ্লো. com
অ্যান্ডি বুট

25

সমস্যাটি হ'ল সত্য প্রকৃতির পরিবর্তে প্রক্সি রেফারেন্স অবজেক্টটিvector<bool> ফেরত দেয় , যাতে সি ++ 98 স্টাইল কোডটি সংকলন না করে। যাইহোক, আধুনিক সি ++ 11 যদি কম্পাইল করার তৈরি করা যেতে পারে এছাড়া একটি প্রক্সি পয়েন্টার বস্তুর ফেরৎ । হাওয়ার্ড হিন্যান্ট এই জাতীয় প্রক্সি রেফারেন্স এবং পয়েন্টার ব্যবহার করার সময় অ্যালগরিদমিক উন্নতির বিবরণ সহ একটি ব্লগ পোস্ট লিখেছেন ।bool * p = &v[0];auto p = &v[0];operator&

স্কট মেয়ার্সের প্রক্সি ক্লাস সম্পর্কে আরও কার্যকর সি ++ তে একটি দীর্ঘ আইটেম 30 রয়েছে । আপনি বিল্টিন প্রকারের প্রায় নকল করতে দীর্ঘ পথ আসতে পারেন : যে কোনও প্রদত্ত প্রকারের জন্য T, একজোড়া প্রক্সি (যেমন reference_proxy<T>এবং iterator_proxy<T>) পারস্পরিকভাবে সামঞ্জস্য করা যায় সেই অর্থে reference_proxy<T>::operator&()এবং iterator_proxy<T>::operator*()একে অপরের বিপরীত।

যাইহোক, কিছু সময়ে এক চাহিদা ফিরে প্রক্সি বস্তু ম্যাপ মত আচরণ করে T*বা T&। পুনরুত্থক প্রক্সিগুলির জন্য, সমস্ত কার্যকারিতা পুনরায় প্রয়োগ না করেই operator->()টেমপ্লেটের Tইন্টারফেসটি ওভারলোড এবং অ্যাক্সেস করতে পারে। তবে, রেফারেন্স প্রক্সিগুলির জন্য আপনার ওভারলোডের প্রয়োজন হবে operator.()এবং এটি বর্তমান সি ++ এ অনুমোদিত নয় (যদিও সেবাস্তিয়ান রেডল বুস্টকন 2013 এ এই জাতীয় প্রস্তাব উপস্থাপন করেছেন )। আপনি .get()রেফারেন্স প্রক্সিটির ভিতরে কোনও সদস্যের মতো ভার্জোজ ওয়ার্কস করতে পারেন , বা রেফারেন্সের অভ্যন্তরে সমস্ত Tইন্টারফেস প্রয়োগ করতে পারেন (এটিই এর জন্য করা হয়vector<bool>::bit_reference), তবে এটি বিল্টিন সিনট্যাক্সটি হারিয়ে ফেলবে বা প্রকার রূপান্তরগুলির জন্য বিল্টিন শব্দার্থবিজ্ঞান নেই এমন ব্যবহারকারী-সংজ্ঞায়িত রূপান্তরগুলি প্রবর্তন করবে (প্রতিটি যুক্তিতে আপনার সর্বাধিক একজন ব্যবহারকারী-সংজ্ঞায়িত রূপান্তর থাকতে পারে)।

টিএল; ডিআর : vector<bool>না কোনও ধারক নয় কারণ স্ট্যান্ডার্ডটির প্রকৃত রেফারেন্স প্রয়োজন, তবে এটি সি ++৯ এর চেয়ে কমপক্ষে সি ++ 11 (অটো) এর সাথে কমপক্ষে একটি ধারকের মতো আচরণ করা যেতে পারে।


10

বিশেষতাকে অনেকেই vector<bool>ভুল বলে মনে করেন ।

একটি কাগজে "সি বিনয়ী বিলুপ্তপ্রায় অঙ্গের লাইব্রেরী যন্ত্রাংশ ++, 17"
একটি প্রস্তাব নেই আংশিক বিশেষায়িত ক্ষেত্র ভেক্টর পুনর্বিচার

স্ট্যান্ড :: ভেক্টরটির বুল আংশিক বিশেষত্বের দীর্ঘ ইতিহাস রয়েছে যা ধারক প্রয়োজনীয়তা পূরণ করে না এবং বিশেষত, এর পুনরাবৃত্তিগুলি এলোমেলো অ্যাক্সেসের পুনরাবৃত্তির প্রয়োজনীয়তা পূরণ করে না। এই ধারকটিকে হ্রাস করার পূর্বের একটি প্রচেষ্টা সি ++ 11, এন 2204 এর জন্য প্রত্যাখ্যান করা হয়েছিল ।


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


5

কিভাবে এটি বাস্তবায়িত হয় দেখুন। এসটিএল টেমপ্লেটগুলিতে ব্যাপকভাবে তৈরি করে এবং তাই শিরোনামগুলি তারা করে কোড থাকে।

উদাহরণস্বরূপ এখানে stdc ++ বাস্তবায়ন দেখুন ।

এছাড়াও যদিও আকর্ষণীয় নয় একটি Stl বিট ভেক্টর অনুসারী হয় llvm :: BitVector থেকে এখানে

এর সারমর্মটি llvm::BitVectorহ'ল একটি নেস্টেড ক্লাস referenceএবং উপযুক্ত সীমাবদ্ধতার সাথে BitVectorআচরণের অনুরূপ করার জন্য উপযুক্ত অপারেটর ওভারলোডিং vectorreferenceপ্রতিটি মানটির জন্য 1 বাইট ব্যবহার না করে আসল বাস্তবায়নটিকে প্রায় বাস্তবের বোলের প্রকৃত অ্যারের মতো আচরণ করতে প্রকৃত বাস্তবায়নটি কীভাবে শ্রেণিবদ্ধ করে তা দেখানোর জন্য নীচের কোডটি একটি সরলীকৃত ইন্টারফেস ।

class BitVector {
public:
  class reference {
    reference &operator=(reference t);
    reference& operator=(bool t);
    operator bool() const;
  };
  reference operator[](unsigned Idx);
  bool operator[](unsigned Idx) const;      
};

এই কোড এখানে চমৎকার বৈশিষ্ট্য আছে:

BitVector b(10, false); // size 10, default false
BitVector::reference &x = b[5]; // that's what really happens
bool y = b[5]; // implicitly converted to bool 
assert(b[5] == false); // converted to bool
assert(b[6] == b[7]); // bool operator==(const reference &, const reference &);
b[5] = true; // assignment on reference
assert(b[5] == true); // and actually it does work.

এই কোডটিতে আসলে একটি ত্রুটি রয়েছে, চালানোর চেষ্টা করুন:

std::for_each(&b[5], &b[6], some_func); // address of reference not an iterator

কাজ করবে না কারণ assert( (&b[5] - &b[3]) == (5 - 3) );ব্যর্থ হবে (এর মধ্যে llvm::BitVector)

এটি খুব সহজ এলএলভিএম সংস্করণ। std::vector<bool>এটিতে কাজকর্মগুলিও রয়েছে। সুতরাং কল for(auto i = b.begin(), e = b.end(); i != e; ++i)কাজ করবে। এবং এছাড়াও std::vector<bool>::const_iterator

তবে এর মধ্যে এখনও সীমাবদ্ধতা রয়েছে std::vector<bool>যা কিছু ক্ষেত্রে এটি আলাদাভাবে আচরণ করে ।


3

এটি http://www.cplusplus.com/references/vector/vector-bool/ থেকে এসেছে

বুলের ভেক্টর এটি ভেক্টরের একটি বিশেষ সংস্করণ, যা টাইপ বুলের উপাদানগুলির জন্য ব্যবহৃত হয় এবং স্থানের জন্য অনুকূলিত হয়।

এটি নীচের পরিবর্তনের সাথে ভেক্টরের অপ্রয়োজনীয় সংস্করণের মতো আচরণ করে:

  • স্টোরেজ অগত্যা বুলের মূল্যগুলির একটি অ্যারে নয়, তবে গ্রন্থাগার বাস্তবায়ন স্টোরেজটিকে অনুকূলিত করতে পারে যাতে প্রতিটি মান
    একক বিটে সংরক্ষণ করা যায়।
  • উপাদানগুলি বরাদ্দকারী অবজেক্টটি ব্যবহার করে নির্মিত হয় না তবে তাদের মানটি সরাসরি অভ্যন্তরীণ স্টোরেজে সঠিক বিটের উপর সেট করা থাকে।
  • সদস্য ফাংশন ফ্লিপ এবং সদস্য অদলবদলের জন্য একটি নতুন স্বাক্ষর।
  • একটি বিশেষ সদস্যের প্রকার, রেফারেন্স, একটি শ্রেণি যা কনটেইনার অভ্যন্তরীণ স্টোরেজে পৃথক বিটগুলিকে অ্যাক্সেস করে এমন একটি ইন্টারফেস যা
    একটি বুল রেফারেন্স অনুকরণ করে। বিপরীতে, সদস্যের ধরণের কনস্ট_রেফারেন্স হ'ল একটি সরল বুল।
  • ধারক দ্বারা ব্যবহৃত পয়েন্টার এবং পুনরাবৃত্তকারী প্রকারগুলি অবশ্যই পয়েন্টার বা মানক পুনরাবৃত্তকারী নয়, যদিও তারা
    তাদের প্রত্যাশিত আচরণের বেশিরভাগ অনুকরণ করে।

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

বিটসেট এমন একটি শ্রেণি যা বিটগুলির স্থির আকারের অ্যারেগুলির জন্য একই কার্যকারিতা সরবরাহ করে।


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