সি ++ 11 রেঞ্জ ভিত্তিক লুপ: মান বা কনস্টের রেফারেন্স অনুসারে আইটেমটি পান


215

পরিসীমা ভিত্তিক লুপগুলির কয়েকটি উদাহরণ পড়তে তারা 1 , 2 , 3 , 4 দুটি প্রধান উপায় প্রস্তাব করে

std::vector<MyClass> vec;

for (auto &x : vec)
{
  // x is a reference to an item of vec
  // We can change vec's items by changing x 
}

অথবা

for (auto x : vec)
{
  // Value of x is copied from an item of vec
  // We can not change vec's items by changing x
}

আমরা হব.

যখন আমাদের vecআইটেম পরিবর্তন করার প্রয়োজন হয় না , আইএমও, উদাহরণগুলি দ্বিতীয় সংস্করণ (মান অনুসারে) ব্যবহার করার পরামর্শ দেয়। কেন তারা এমন কিছু প্রস্তাব দেয় না যা constউল্লেখ করে (কমপক্ষে আমি সরাসরি কোনও পরামর্শ পাইনি):

for (auto const &x : vec) // <-- see const keyword
{
  // x is a reference to an const item of vec
  // We can not change vec's items by changing x 
}

ভাল না? এটি প্রতিটি যখন পুনরাবৃত্তির অনর্থক অনুলিপিটি এড়ায় না const?

উত্তর:


390

আপনি যদি আইটেমগুলি পরিবর্তন করতে না চান এবং অনুলিপিগুলি এড়াতে চান না , তবে auto const &সঠিক পছন্দ:

for (auto const &x : vec)

যে আপনাকে ব্যবহারের পরামর্শ দেয় সে auto &ভুল। তাদের উপেক্ষা কর.

এখানে সংশোধন করা হল:

  • auto xআপনি যখন অনুলিপি নিয়ে কাজ করতে চান তা চয়ন করুন ।
  • auto &xআপনি যখন আসল আইটেমগুলির সাথে কাজ করতে চান তখন চয়ন করুন এবং সেগুলি সংশোধন করতে পারেন।
  • auto const &xআপনি যখন আসল আইটেমগুলির সাথে কাজ করতে চান তা চয়ন করুন এবং সেগুলি সংশোধন করবেন না।

21
দুর্দান্ত উত্তরের জন্য ধন্যবাদ। আমার ধারণা এটি const auto &xআপনার তৃতীয় পছন্দের সমান এটিও নির্দেশ করা উচিত ।
স্মাগ

7
@ মিলসকোট: সমান। (এবং "তবে এটি একই সিনট্যাক্স" বলতে আপনার কী বোঝায় ? বাক্য গঠনটি ভিন্নভাবে ভিন্ন different)
নওয়াজ

14
অনুপস্থিত: auto&&যখন আপনি অযথা অনুলিপি তৈরি করতে চান না, এবং আপনি এটি পরিবর্তন করেন বা না করেন সেদিকে খেয়াল রাখবেন না এবং আপনি কেবল কাজ করতে চান।
ইয়াক্ক - অ্যাডাম নেভ্রামামন্ট

4
আপনি যদি কেবল ইনট / ডাবলের মতো মৌলিক ধরণের সাথে কাজ করে থাকেন তবে কি রেফারেন্স পার্থক্যটি অনুলিপিগুলিতে প্রযোজ্য?

4
@ ক্র্যারেট: আমি সামগ্রিক গতি সম্পর্কে মন্তব্য করতে পারি না এবং আমি মনে করি যে এটি প্রথমে কোনও প্রোফাইল না করেই কেউ পারবে না। সত্যি বলতে কী, আমি কোডের স্পষ্টতার চেয়ে গতিতে আমার পছন্দকে ভিত্তি করব না। আমি যদি অপরিবর্তনীয়তা চাই, আমি constঅবশ্যই এটি ব্যবহার করব। তবে তা হবে কি না auto const &, বা auto const কিছুটা তফাত আছে। আমি auto const &আরও নিয়মিত হতে চাই ।
নওয়াজ

23

আপনার যদি একটি std::vector<int>বা থাকে std::vector<double>তবে এটির autoপরিবর্তে (মান কপি সহ) ব্যবহার করার পক্ষে এটি ঠিক আছে const auto&, যেহেতু একটি intবা একটি অনুলিপি doubleকরা সস্তা:

for (auto x : vec)
    ....

তবে আপনার যদি একটি থাকে std::vector<MyClass>, যেখানে MyClassকিছু অ-তুচ্ছ কপি শব্দার্থবিজ্ঞান রয়েছে (যেমন std::string, কিছু জটিল কাস্টম শ্রেণি ইত্যাদি) তবে আমি const auto&গভীর কপিগুলি এড়ানোর জন্য ব্যবহার করার পরামর্শ দেব :

for (const auto & x : vec)
    ....

3

যখন আমাদের vecআইটেম পরিবর্তন করার দরকার নেই , উদাহরণগুলি প্রথম সংস্করণটি ব্যবহার করার পরামর্শ দেয়।

তারপরে তারা একটি ভুল পরামর্শ দেয়।

কেন তারা এমন কিছু প্রস্তাব দেয় না যা কোন উল্লেখগুলি উল্লেখ করে

কারণ তারা একটি ভুল পরামর্শ দেয় :-) আপনি যা উল্লেখ করেছেন তা সঠিক। আপনি যদি কেবল কোনও অবজেক্টটি পর্যবেক্ষণ করতে চান তবে একটি অনুলিপি তৈরি করার দরকার নেই constএবং এটির কোনও উল্লেখ ছাড়াই করার দরকার নেই ।

সম্পাদনা করুন:

আমি যে সমস্ত রেফারেন্সগুলিকে লিঙ্ক করেছি সেগুলি দেখছি intমানগুলি বা অন্য কোনও মৌলিক ডেটা ধরণের ব্যাপ্তিতে পুনরাবৃত্তি করার উদাহরণ সরবরাহ করে । intসেক্ষেত্রে যেহেতু একটি অনুলিপি করা ব্যয়বহুল নয় , তাই অনুলিপি তৈরি করা মূলত পর্যবেক্ষক হওয়ার (এর চেয়ে বেশি দক্ষ না হলে) সমতুল্য const &

এটি অবশ্য ব্যবহারকারী-সংজ্ঞায়িত প্রকারের ক্ষেত্রে নয়। ইউডিটি অনুলিপি করা ব্যয়বহুল হতে পারে এবং যদি আপনার অনুলিপি তৈরি করার কোনও কারণ না থাকে (যেমন আসলটি পরিবর্তন না করে পুনরুদ্ধার করা বস্তুটি সংশোধন করা) তবে এটি ব্যবহার করা ভাল const &


1

আমি এখানে বিপরীতে যাচ্ছি এবং বলব auto const &লুপের উপর ভিত্তি করে কোনও রেঞ্জের প্রয়োজন নেই । আপনি যদি মনে করেন নীচের ফাংশনটি নির্বোধ (তার উদ্দেশ্য নয়, তবে এটি যেভাবে লেখা হয়েছে):

long long SafePop(std::vector<uint32_t>& v)
{
    auto const& cv = v;
    long long n = -1;
    if (!cv.empty())
    {
        n = cv.back();
        v.pop_back();
    }
    return n;
}

এখানে, লেখক vসমস্ত ক্রিয়াকলাপের জন্য যাঁর ভি পরিবর্তন করে না , এটি ব্যবহারের জন্য একটি দৃ const় রেফারেন্স তৈরি করেছেন This এটি মূর্খ, আমার মতে, এবং একই যুক্তিটি auto const &কেবলমাত্র পরিবর্তে লুপের জন্য ভিত্তি করে একটি পরিসরে পরিবর্তনশীল হিসাবে ব্যবহার করার জন্য তৈরি করা যেতে পারে auto &


3
@ বেঞ্জামিনলিন্ডলি: সুতরাং আমি অনুমান করতে পারি যে আপনি const_iteratorলুপের জন্যও বিতর্ক করবেন ? আপনি কীভাবে নিশ্চিত হন যে আপনি যখন এটি পুনরুক্ত করবেন তখন কোনও ধারক থেকে মূল আইটেমগুলি পরিবর্তন করবেন না?
নওয়াজ

2
@ বেনজামিন লিন্ডলি: আপনার কোড ব্যতীত সংকলন হবে না কেন const_iterator? আমাকে অনুমান করা যাক, ধারক যা আপনি পুনরুক্তিকারীর উপর হয় const। তবে কেন এটি constশুরু হয়? কোথাও আপনি constকি নিশ্চিত করতে ব্যবহার করছেন ?
নওয়াজ

8
বস্তু তৈরির constসুবিধা ক্লাসে private/ ব্যবহার করার সুবিধার মতো protected। এটি আরও ভুল এড়ানো।
মাসউদ

2
@ বেঞ্জামিনলিন্ডলি: ওহ, আমি এটি উপেক্ষা করেছি। তারপরে এই ক্ষেত্রে বাস্তবায়নটিও নির্বোধ। তবে যদি সেই ফাংশনটি সংশোধন না করা হয় vতবে বাস্তবায়নটি আইএমওতে হবে। এবং যদি লুপ কখনই সেই বস্তুগুলির মধ্য দিয়ে পুনরাবৃত্তি করে না তবে এটিতে একটি রেফারেন্স দেওয়া আমার কাছে ঠিক হবে const। আমি যদিও আপনার পয়েন্ট দেখতে। খনিটি হ'ল লুপটি কোনও কোড ইউনিটের প্রতিনিধিত্ব করে ফাংশনটির মতোই, এবং সেই ইউনিটের মধ্যে এমন কোনও নির্দেশ নেই যা মান পরিবর্তন করতে হবে। সুতরাং, আপনি constযেমন কোনও constসদস্য ফাংশনটি করবেন তেমন পুরো ইউনিটটিকে "ট্যাগ" করতে পারেন ।
অ্যান্ডি প্রোল 21

1
সুতরাং আপনি মনে const &করেন পরিসীমা ভিত্তিক নির্বোধ, কারণ আপনি কোনও কাল্পনিক প্রোগ্রামারের একটি অপ্রাসঙ্গিক কাল্পনিক উদাহরণ লিখেছেন যিনি সিভি- যোগ্যতার সাথে নির্বোধ কিছু করেছিলেন? ... ঠিক আছে তাহলে
আন্ডারস্কোর_ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.