সি ++ এসটিএলে কনস্টিটিউটরেটর এবং নন-কনস্ট্যান্ট ইটারেটরের মধ্যে পার্থক্য কী?


139

const_iteratorএবং আ এর মধ্যে পার্থক্য কী এবং iteratorআপনি অন্যটির উপরে কোনটি ব্যবহার করবেন?


1
ঠিক আছে, নাম কনস্টিটিউটরেটরের মত শোনাচ্ছে যে এটির পুনরুক্তিকারী কনস্ট, অন্যদিকে এই পুনরাবৃত্তিকে যে জিনিসটি দেখানো হয়েছে তা আসল কনস্টেট const
টেল্কডস্কোবিডা

উত্তর:


124

const_iterators আপনাকে যে মানগুলি নির্দেশ করে সেগুলি নিয়মিত করার জন্য আপনাকে সেগুলি পরিবর্তন করতে দেয় iteratorনা।

সি ++ তে সমস্ত কিছুর মতো, সর্বদা পছন্দ করুন const, যদি না নিয়মিত পুনরাবৃত্তিকারীদের ব্যবহার করার কোনও ভাল কারণ না থাকে (যেমন আপনি এই সত্যটি ব্যবহার করতে চান যে তারা constপয়েন্ট-টু মান পরিবর্তন করে না )।


8
একটি নিখুঁত বিশ্বের ক্ষেত্রে হবে। তবে সি ++ কনস্টের সাথে কেবল সেই ব্যক্তিটির মতোই দুর্দান্ত যে কোডটি লিখেছিল :(
জেয়ার্ডপাড়

পরিবর্তনীয় একটি খুব ভাল কারণে বিদ্যমান। এটি খুব কমই ব্যবহৃত হয় এবং গুগল কোড অনুসন্ধানের দিকে তাকালে বৈধ ব্যবহারের ন্যায্য শতাংশ রয়েছে বলে মনে হয়। মূলশব্দটি একটি খুব শক্তিশালী অপ্টিমাইজেশন সরঞ্জাম, এবং এটি সরিয়ে ফেলার মতো নয় যা কনস্ট -যথার্থতা উন্নীত করবে ( কাশিপয়েন্টারসৌঘান্ডকোফারেন্সিনসফ )
কপপ্রো

2
আরও একটি শক্তিশালী হ্যাক মত। আমি 'মিউটটেবল' কীওয়ার্ড ব্যবহারের ক্ষেত্রে যে সমস্ত উদাহরণ দেখেছি, তার মধ্যে একটি ছাড়া একটি সঠিক সূচক ছিল যে কোডটি খারাপভাবে লেখা হয়েছিল এবং ত্রুটিগুলি ঘটাতে হ্যাক হিসাবে পরিবর্তনের প্রয়োজন ছিল।
জন ডিবলিং

7
এটির বৈধ ব্যবহার রয়েছে যেমন কোনও কনস্টের ক্লাসের মধ্যে দীর্ঘ গণনার ফলাফলগুলি ক্যাশে করা। অন্যদিকে, আমি প্রায় বিশ বছরের সি ++ বিকাশের ক্ষেত্রে একমাত্র পরিবর্তন করতে পেরেছি that's
হেড করুন

কনস্টিটেটার ব্যবহারের জন্য সাধারণ উদাহরণটি যখন ঘটনাকারীর কোনও মূল্য হয়
টেল্কস্কোবিডি

40

তাদের বেশিরভাগ স্ব-ব্যাখ্যামূলক হওয়া উচিত। যদি পুনরাবৃত্তিকারী টাইপ টির একটি উপাদানকে নির্দেশ করে, তবে কনস্ট_টিরেটর 'কনস্ট টি' টাইপের একটি উপাদানকে নির্দেশ করে।

এটি মূলত পয়েন্টারের ধরণের সমতুল্য:

T* // A non-const iterator to a non-const element. Corresponds to std::vector<T>::iterator
T* const // A const iterator to a non-const element. Corresponds to const std::vector<T>::iterator
const T* // A non-const iterator to a const element. Corresponds to std::vector<T>::const_iterator

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


1
"একটি দৃ const় পুনরাবৃত্তি সর্বদা একই উপাদানকে নির্দেশ করে," এটি ভুল।
জন ডিবলিং

2
তা কিভাবে? অনুপস্থিত আন্ডারস্কোরটি নোট করুন। আমি কনস্ট স্ট্যান্ড :: ভেক্টর <T> :: পুনরুদ্ধারের সাথে স্টেড :: ভেক্টর <T> :: কনস্টিটিউটরেটর এর বৈকল্পিকের বিপরীতে রয়েছি। পূর্ববর্তী ক্ষেত্রে, পুনরুক্তিটি নিজেই কনস্ট, সুতরাং এটি সংশোধন করা যায় না, তবে যে উপাদানটি উল্লেখ করে তা অবাধে পরিবর্তন করা যেতে পারে।
jalf

4
আহ আমি দেখি. হ্যাঁ আমি অনুপস্থিত আন্ডারস্কোর মিস করেছি।
জন ডিবলিং

3
মধ্যে তনিমা ব্যাখ্যা জন্য সম্মত @JohnDibling const iteraterএবং const_iterator
কিংবদন্তি

8

Unfortunaty, STL পাত্রে জন্য পদ্ধতি অনেক সময় লাগে iterators পরিবর্তে const_iterators পরামিতি হিসেবে। সুতরাং আপনার যদি কনস্টিটেটর থাকে তবে আপনি বলতে পারবেন না যে "এই পুনরুক্তিকারীটি যে উপাদানটির দিকে ইঙ্গিত করে" তার আগে একটি উপাদান সন্নিবেশ করান "(আমার মতে এ জাতীয় কথা ধারণামূলকভাবে লঙ্ঘন নয়)। আপনি যদি যাইহোক এটি করতে চান, আপনাকে এটি স্ট্যান্ড :: অগ্রিম () বা বুস্ট :: পরবর্তী () ব্যবহার করে একটি নন-কনস্ট্যান্ট পুনরায় রূপান্তর করতে হবে । যেমন। বুস্ট :: পরবর্তী (ধারক.বেগিন (), স্টাড :: দূরত্ব (ধারক.বেগিন (), the_const_iterator_we_ant_to_unconst)) । তাহলে ধারক একটি হয় এসটিডি :: তালিকা , তাহলে সেই কলের জন্য সময় চলমান হবে হে (ঢ)

সুতরাং এটি করা "যৌক্তিক" যেখানেই কনস্ট যুক্ত করার সার্বজনীন নিয়মটি এসটিএল পাত্রে চলে আসে তখন সর্বজনীন নয়।

তবে বুস্ট কনটেইনারগুলি কনস্ট_টিরেটর নেয় (উদাঃ বুস্ট :: আনর্ডারড_ম্যাপ :: ইরেজ ())। সুতরাং যখন আপনি বুস্ট পাত্রে ব্যবহার করেন আপনি "কনস্ট আগ্রাসী" হতে পারেন। যাইহোক, কেউ কি জানেন যে কখন বা এসটিএল পাত্রে স্থির হবে?


1
এটি মতামতের বিষয় হতে পারে। ক্ষেত্রে vectorএবং dequeসমস্ত বিদ্যমান iterators, যা খুবই নয় ঢোকাতে এক উপাদান, অকার্যকর const। তবে আমি আপনার বক্তব্য দেখতে পাচ্ছি। এই ধরনের ক্রিয়াকলাপগুলি constকনটেনার-বেকারত্ব দ্বারা সুরক্ষিত থাকে , পুনরাবৃত্তিকারী নয়। এবং আমি অবাক হয়েছি কেন স্ট্যান্ডার্ড কনটেইনার ইন্টারফেসে কনস্ট-টু-ননকনস্ট পুনরায় রূপান্তর ফাংশন নেই।
পোটোটোভটার

আপনি সঠিক Potatoswatter, আমি নিঃশর্ত থাকি, এটা রেণ্ডম এক্সেস পাত্রে জন্য মতামত এবং একটি ব্যাপার container.begin () + + (the_const_iterator_we_want_to_unconst - container.begin ()) হয় হে (1) যাহাই হউক না কেন। আমি আরও আশ্চর্য হই যে কেন নন-এলোমেলো অ্যাক্সেস কনটেইনারগুলির জন্য কোনও রূপান্তর ফাংশন নেই, তবে সম্ভবত কোনও ভাল কারণ আছে? আপনি কি জানেন যে অ-র্যান্ডম অ্যাক্সেস কনটেইনারগুলির ক্রিয়াকলাপগুলি কনস্টিটারগুলি গ্রহণ করে না এমন কোনও কারণ আছে ?
ম্যাগনাস অ্যান্ডারমো

"এই জাতীয় কথা বলাই আমার পক্ষে মতামত হিসাবে নিয়ম লঙ্ঘন নয়" - এটি একটি খুব আকর্ষণীয় মন্তব্য, বিষয়টি নিয়ে আমার নিম্নলিখিত মতামত রয়েছে। সাধারণ পয়েন্টারগুলির সাহায্যে, কেউ বলতে পারেন int const * foo; int * const foo;এবং int const * const foo;তিনটিই বৈধ এবং কার্যকর, প্রতিটি তাদের নিজস্ব উপায়ে। std::vector<int> const barদ্বিতীয়টির মতোই হওয়া উচিত, তবে দুর্ভাগ্যক্রমে এটি প্রায়শই তৃতীয়টির মতো হয়। সমস্যার মূল কারণটি হ'ল আমরা বলতে পারি না std::vector<int const> bar;যখন এর অর্থ কোনও int const *foo;ভেক্টরের মতো একই প্রভাব পাওয়ার কোনও উপায় নেই ।
dgnuff

5

আপনি যখনই পারেন কনস্টিটিউটরেটর ব্যবহার করুন , যখন আপনার অন্য কোনও পছন্দ নেই তখন পুনরুক্তি ব্যবহার করুন ।


4

ন্যূনতম চলমান উদাহরণ

নন-কনস্ট্যান্ট ইটারেটরগুলি আপনাকে কী নির্দেশ করে তা সংশোধন করার অনুমতি দেয়:

std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();
*it = 1;
assert(v[0] == 1);

কনস্টেট পুনরাবৃত্তিকারীরা এটি করে না:

const std::vector<int> v{0};
std::vector<int>::const_iterator cit = v.begin();
// Compile time error: cannot modify container with const_iterator.
//*cit = 1;

উপরে দেখানো হিসাবে, v.begin()হয় constওভারলোড, এবং আয় হয় iteratorবা const_iteratorধারক ভেরিয়েবলের const-অন্তরীপ উপর ভিত্তি করে:

একটি সাধারণ ক্ষেত্রে যেখানে const_iteratorপপ আপ হয় thisকোনও constপদ্ধতির অভ্যন্তরে ব্যবহৃত হয় :

class C {
    public:
        std::vector<int> v;
        void f() const {
            std::vector<int>::const_iterator it = this->v.begin();
        }
        void g(std::vector<int>::const_iterator& it) {}
};

constতোলে thisযার ফলে const, this->vconst।

আপনি এটির সাথে সাধারণত এটি ভুলে যেতে পারেন auto, তবে আপনি যদি এই পুনরুক্তিগুলি চারপাশে পাস করতে শুরু করেন তবে আপনাকে পদ্ধতি স্বাক্ষরের জন্য তাদের সম্পর্কে ভাবতে হবে।

অনেকটা কনস্ট্যান্ড এবং নন-কনস্টের মতোই আপনি নন-কনস্ট থেকে কনস্টে সহজে রূপান্তর করতে পারেন তবে অন্য উপায়ে নয়:

std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();

// non-const to const.
std::vector<int>::const_iterator cit = it;

// Compile time error: cannot modify container with const_iterator.
//*cit = 1;

// Compile time error: no conversion from const to no-const.
//it = ci1;

কোনটি ব্যবহার করবেন: বনামের সাথে const intসাদৃশ্যযুক্ত int: যখনই আপনি তাদের ব্যবহার করতে পারেন কনস্টেটের পুনরাবৃত্তিগুলি পছন্দ করুন (যখন আপনার সাথে ধারকটি সংশোধন করার প্রয়োজন হবে না), কোনও সংশোধন না করে পড়ার আপনার উদ্দেশ্যটি আরও ভাল করে ডকুমেন্ট করতে।


0

(যেমন অন্যেরা বলেছেন) কনস্টেটাইটারেটর আপনাকে যে উপাদানগুলিতে এটি নির্দেশ করে তা সংশোধন করার অনুমতি দেয় না, এটি কনস্টের ক্লাস পদ্ধতিগুলির মধ্যে দরকারী। এটি আপনাকে আপনার অভিপ্রায় প্রকাশ করার অনুমতি দেয়।


0

ঠিক আছে আমাকে ধীরে ধীরে পুনরাবৃত্তকারী ব্যবহার না করে প্রথমে খুব সাধারণ উদাহরণ দিয়ে এটি ব্যাখ্যা করতে পারি বিবেচনা করুন আমাদের কাছে এলোমেলো পূর্ণসংখ্যা সংগ্রহ "এলোমেলো ডেটা" রয়েছে

    for(vector<int>::iterator i = randomData.begin() ; i != randomData.end() ; ++i)*i = 0;
for(vector<int>::const_iterator i = randomData.begin() ; i!= randomData.end() ; ++i)cout << *i;

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

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