উত্তর:
এটা বেশ সহজ। বলুন আমার কাছে ভেক্টর রয়েছে:
std::vector<int> vec;
আমি কিছু তথ্য দিয়ে এটি পূরণ। তারপরে আমি এটিতে কিছু পুনরাবৃত্তি পেতে চাই। তাদের কাছাকাছি যেতে পারে। হতে পারে std::for_each
:
std::for_each(vec.begin(), vec.end(), SomeFunctor());
C ++ 03 এ, প্যারামিটারটি পাওয়ার সাথে সাথে এটি সংশোধনSomeFunctor
করতে সক্ষম হয়েছিল । অবশ্যই, মান দ্বারা বা তার পরামিতি নিতে পারে , তবে এটি নিশ্চিত করার কোনও উপায় নেই। এর মতো নির্বোধ কিছু না করে:SomeFunctor
const&
const std::vector<int> &vec_ref = vec;
std::for_each(vec_ref.begin(), vec_ref.end(), SomeFunctor());
এখন, আমরা পরিচয় করিয়ে দেই cbegin/cend
:
std::for_each(vec.cbegin(), vec.cend(), SomeFunctor());
এখন, আমাদের সিনট্যাকটিক আশ্বাস রয়েছে যা SomeFunctor
ভেক্টরের উপাদানগুলিকে সংশোধন করতে পারে না (অবশ্যই কোনও কনস্ট-কাস্ট ছাড়াই)। আমরা স্পষ্টতই const_iterator
এস পাই , এবং সেইজন্য SomeFunctor::operator()
তাদের সাথে ডাকা হবে const int &
। যদি এটি এর পরামিতি হিসাবে নেয় তবে int &
সি ++ একটি সংকলক ত্রুটি জারি করবে।
সি ++ 17 এই সমস্যার একটি আরো মার্জিত সমাধান আছে: std::as_const
। ভাল, পরিসীমা ভিত্তিক ব্যবহার করার সময় কমপক্ষে এটি মার্জিত for
:
for(auto &item : std::as_const(vec))
এটি কেবল const&
যে বস্তুটি সরবরাহ করা হয় তাতে ফিরে আসে ।
std::cbegin/cend
যেভাবে std::begin/std::end
অস্তিত্ব রয়েছে সেভাবে কোনও ফ্রি ফাংশন নেই। এটি কমিটি দ্বারা একটি তদারকি ছিল। যদি এই ফাংশনগুলি উপস্থিত থাকে, তবে এটি সাধারণত তাদের ব্যবহার করার উপায় ছিল।
std::cbegin/cend
সি ++ 14 এ যুক্ত করা হবে। দেখুন en.cppreferences.com/w/cpp/iterator/begin
for(auto &item : std::as_const(vec))
সমান for(const auto &item : vec)
?
const
রেফারেন্সটি রেখে আইটেমটি পরিবর্তন করা হবে না । নিকলের কনটেইনারটি কনস্ট হিসাবে দেখায়, তাই রেফারেন্সটি auto
হ্রাস করে const
। আইএমও auto const& item
সহজ এবং পরিষ্কার। std::as_const()
এখানে কেন ভাল তা স্পষ্ট নয় ; আমি দেখতে পেলাম const
যে জেনেরিক কোডটি নন-এমন কিছু পাস করার সময় এটি দরকারী হবে যেখানে আমরা যে ধরণের ব্যবহার করতে পারি তা নিয়ন্ত্রণ করতে পারি না, তবে পরিসীমা সহ for
, আমরা এটি করতে পারি, সুতরাং এটি কেবল আমার কাছে বাড়তি আওয়াজ বলে মনে হচ্ছে।
নিকোল বোলাস তার উত্তরে যা বলেছিল তার বাইরে নতুন auto
কীওয়ার্ডটি বিবেচনা করুন :
auto iterator = container.begin();
সাথে auto
, এটি নিশ্চিত করার উপায় নেই যে কোনও begin()
ধ্রুবক ধারক রেফারেন্সের জন্য একটি ধ্রুবক অপারেটর ফিরে আসে। সুতরাং এখন আপনি কি:
auto const_iterator = container.cbegin();
const_iterator
কাছে কেবল অন্য শনাক্তকারী। কোনও সংস্করণই সাধারণ সদস্য টাইপডেফসের চেহারা decltype(container)::iterator
বা ব্যবহার করে না decltype(container)::const_iterator
।
const_iterator
সঙ্গে auto
লিখুন নামক একটি অক্জিলিয়ারী ফাংশন টেমপ্লেট: make_const
অবজেক্ট যুক্তি যোগ্যতা।
এটি ব্যবহারিক ব্যবহারের ক্ষেত্র হিসাবে গ্রহণ করুন
void SomeClass::f(const vector<int>& a) {
auto it = someNonConstMemberVector.begin();
...
it = a.begin();
...
}
অ্যাসাইনমেন্ট ব্যর্থ হয়েছে কারণ it
একটি ননকনস্ট পুনরুক্তিকারী। আপনি যদি প্রাথমিকভাবে সিবেগিন ব্যবহার করেন তবে পুনরাবৃত্তির সঠিক টাইপটি থাকতে পারে।
Http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1674.pdf থেকে :
যাতে কোনও প্রোগ্রামার সরাসরি কোনও কনস্ট্যান্ট কনটেইনার থেকেও কনস্টেটিটর পেতে পারে
তারা এই উদাহরণ দিয়েছেন
vector<MyType> v;
// fill v ...
typedef vector<MyType>::iterator iter;
for( iter it = v.begin(); it != v.end(); ++it ) {
// use *it ...
}
যাইহোক, যখন কোনও ধারক ট্র্যাভারসাল কেবলমাত্র পরিদর্শন করার উদ্দেশ্যে করা হয়, তখন কনস্টাইলারকে কনস্ট-শোধনের লঙ্ঘনের জন্য নির্ধারিত করার জন্য কনস্টেটার ব্যবহার করা সাধারণত পছন্দসই অনুশীলন is
নোট কাজ কাগজের এছাড়াও অ্যাডাপ্টারের টেমপ্লেট উল্লেখ, যে এখন যেমন চূড়ান্ত হয়েছে std::begin()
এবং std::end()
এবং যে এছাড়াও নেটিভ অ্যারে সঙ্গে কাজ করে। সম্পর্কিত std::cbegin()
এবং std::cend()
কৌতূহলীভাবে এই সময় হিসাবে নিখোঁজ, কিন্তু তারা এছাড়াও যুক্ত হতে পারে।
এই প্রশ্নটিতে কেবল হোঁচট খেয়েছে ... আমি জানি এটির উত্তরের উত্তর দেওয়া হয়েছে এবং এটি কেবল একটি পাশের নোড ...
auto const it = container.begin()
তখন অন্যরকম auto it = container.cbegin()
পার্থক্যের জন্য int[5]
(পয়েন্টার ব্যবহার করে, যা আমি জানি যে শুরুর পদ্ধতিটি নেই তবে পার্থক্যটি ভালভাবে দেখায় ... তবে সি ++ 14 এ কাজ করবে std::cbegin()
এবং std::cend()
এটি এখানে যখন মূলত কোনটি ব্যবহার করা উচিত) ...
int numbers = array[7];
const auto it = begin(numbers); // type is int* const -> pointer is const
auto it = cbegin(numbers); // type is int const* -> value is const
iterator
এবং const_iterator
উত্তরাধিকারের সম্পর্ক রয়েছে এবং অন্য ধরণের সাথে তুলনা করা বা নির্ধারিত হলে একটি অন্তর্নিহিত রূপান্তর ঘটে।
class T {} MyT1, MyT2, MyT3;
std::vector<T> MyVector = {MyT1, MyT2, MyT3};
for (std::vector<T>::const_iterator it=MyVector.begin(); it!=MyVector.end(); ++it)
{
// ...
}
ব্যবহার cbegin()
এবং cend()
এই ক্ষেত্রে কর্মক্ষমতা বৃদ্ধি করবে।
for (std::vector<T>::const_iterator it=MyVector.cbegin(); it!=MyVector.cend(); ++it)
{
// ...
}
const
এর মূল উপকারিতা হল কর্মক্ষমতা (যা এটি নয়: এটি শব্দার্থগতভাবে সঠিক এবং নিরাপদ কোড)। তবে, আপনার একটি বক্তব্য থাকার সময়, (এ) auto
এটিকে একটি নন-ইস্যু করে তোলে; (খ) পারফরম্যান্স সম্পর্কে কথা বলতে গিয়ে, আপনার এখানে করা উচিত ছিল এমন একটি প্রধান জিনিসটি মিস করেছেন: end
পুনরুক্তির for
পরিবর্তে একটি নতুন অনুলিপি না পাওয়ার পরিবর্তে পুনরুক্তিটির কপিটি লুপের ইনি-শর্তে ঘোষণা করে এবং তার সাথে তুলনা করুন প্রতিটি পুনরাবৃত্তির জন্য মান। এটি আপনার বক্তব্যকে আরও ভাল করে তুলবে। : পি
const
ভাল পারফরম্যান্স অর্জনে সহায়তা করতে পারে, const
কীওয়ার্ডে নিজেই কিছু ম্যাজিকের কারণে নয়, কারণ সংকলক কিছু অপ্টিমাইজেশন সক্ষম করতে পারে যদি এটি জানে যে ডেটা সংশোধন করা হবে না, যা অন্যথায় সম্ভব হবে না। এর লাইভ উদাহরণের জন্য জেসন টার্নারের আলাপ থেকে এই বিটটি দেখুন ।
const
(প্রায় পরোক্ষভাবে) পারফরম্যান্স সুবিধার দিকে নিয়ে যেতে পারে; কেবল কেউ যদি এটি পড়ে তবে মনে করে " const
উত্পন্ন কোডটি কোনওভাবেই প্রভাবিত না হলে আমি যুক্ত করে বিরক্ত করব না ", যা সত্য নয়।
এটির সহজ, সিবেগিন একটি ধ্রুবক পুনরাবৃত্তি প্রদান করে যেখানে শুরু কেবলমাত্র একটি পুনরাবৃত্তিকে দেয়
আরও ভাল বোঝার জন্য এখানে দুটি পরিস্থিতি নেওয়া যায়
দৃশ্যপট 1 :
#include <iostream>
using namespace std;
#include <vector>
int main(int argc, char const *argv[])
{
std::vector<int> v;
for (int i = 1; i < 6; ++i)
{
/* code */
v.push_back(i);
}
for(auto i = v.begin();i< v.end();i++){
*i = *i + 5;
}
for (auto i = v.begin();i < v.end();i++){
cout<<*i<<" ";
}
return 0;
}
এটি চলবে কারণ এখানে পুনরাবৃত্তিকারী আমি ধ্রুবক নয় এবং 5 দ্বারা বাড়ানো যেতে পারে
এখন আসুন সিবেগিন ব্যবহার করুন এবং এগুলি স্থির পুনরাবৃত্তির দৃশ্যের হিসাবে চিহ্নিত করুন - 2:
#include <iostream>
using namespace std;
#include <vector>
int main(int argc, char const *argv[])
{
std::vector<int> v;
for (int i = 1; i < 6; ++i)
{
/* code */
v.push_back(i);
}
for(auto i = v.cbegin();i< v.cend();i++){
*i = *i + 5;
}
for (auto i = v.begin();i < v.end();i++){
cout<<*i<<" ";
}
return 0;
}
এটি কাজ করে না, কারণ আপনি সিবিগিন এবং সেন্ট ব্যবহার করে মানটি আপডেট করতে পারবেন না যা ধ্রুবক পুনরাবৃত্তিকে ফেরত দেয়