কেন স্ট্যান্ড :: কিউ :: পপ রিটার্ন মান নয়?


123

আমি এই পৃষ্ঠাটি দিয়ে গিয়েছিলাম তবে আমি এর কারণটি পাই না। সেখানে উল্লেখ করা হয়েছে যে

"একেবারেই কোনও মূল্য না ফেরানো এবং সারির সামনের দিকে মূল্য পরীক্ষা করার জন্য ক্লায়েন্টদের সামনে () ব্যবহার করার পক্ষে এটি আরও বোধগম্য"

তবে সামনে () থেকে কোনও উপাদান পরিদর্শন করার জন্যও সেই উপাদানটিকে লভ্যালুতে অনুলিপি করা প্রয়োজন। এই কোড বিভাগে উদাহরণস্বরূপ

std::queue<int> myqueue;
int myint;
int result;
std::cin >> myint;
myqueue.push (myint);

/ * এখানে আরএইচএসে অস্থায়ী তৈরি করা হবে যা ফলাফলের জন্য নির্ধারিত হবে এবং যদি রেফারেন্স অনুসারে রিটার্ন আসে তবে পপ অপারেশনের পরে ফলাফলটি অবৈধ রেন্ডার হবে * /

result = myqueue.front();  //result.
std::cout << ' ' << result;
myqueue.pop();

পঞ্চম লাইনে cout অবজেক্ট প্রথমে myqueue.front () এর একটি অনুলিপি তৈরি করে তারপরে ফলাফলটি নির্ধারিত করে। সুতরাং, পার্থক্য কি, পপ ফাংশন একই জিনিস করতে পারে।


কারণ এইভাবে প্রয়োগ করা হয়েছে (যেমন, void std::queue::pop();)।
101010

প্রশ্নের উত্তর দেওয়া হয়েছে, তবে একটি সিডেনোট হিসাবে: আপনি যদি সত্যিই ফিরে আসা কোনও পপ চান তবে এটি একটি বিনামূল্যে ফাংশন সহ সহজেই প্রয়োগ করা যেতে পারে: আদর্শ one.com/lnUzf6
এরেরিকা

1
আপনার লিঙ্কটি এসটিএল ডকুমেন্টেশনের। তবে আপনি সি ++ স্ট্যান্ডার্ড লাইব্রেরি সম্পর্কে জিজ্ঞাসা করছেন। বিভিন্ন জিনিস।
janchopanza

5
"তবে কোনও উপাদান থেকে তদন্ত করার front()জন্যও সেই উপাদানটির মূল্য কপি করা দরকার" - না এটি তা করে না। frontএকটি রেফারেন্স দেয়, কোনও মান দেয় না। এটি অনুলিপি না করে আপনি যে মানটি উল্লেখ করেছেন তা পরীক্ষা করতে পারেন।
মাইক সিমুর

1
@KeminZhou আপনি যে মডেলটি বর্ণনা করেছেন তার একটি অনুলিপি প্রয়োজন। হতে পারে. আপনি যদি সারির মাল্টিপ্লেক্স ব্যবহার করতে চান তবে হ্যাঁ, আপনার কিউতে লকটি মুক্ত করার আগে একটি অনুলিপি তৈরি করতে হবে। তবে, আপনি যদি কেবল ইনপুট এবং আউটপুটকে আলাদা করার বিষয়ে চিন্তা করেন তবে সামনের অংশটি পরীক্ষা করতে আপনার কোনও লক লাগবে না । আপনি এটি গ্রহণ না করে এবং কল করার প্রয়োজন না হওয়া পর্যন্ত আপনি লক করার জন্য অপেক্ষা করতে পারেন pop()। আপনি যদি ব্যবহার করেন std::queue<T, std::list<T>>তবে এ front()দ্বারা অবৈধ হওয়া থেকে সরবরাহ করা রেফারেন্স সম্পর্কে কোনও উদ্বেগ নেই push()। তবে আপনাকে অবশ্যই আপনার ব্যবহারের ধরণটি জানতে হবে এবং আপনার সীমাবদ্ধতাগুলি ডকুমেন্ট করা উচিত।
jwm

উত্তর:


105

সুতরাং, পার্থক্য কি, পপ ফাংশন একই জিনিস করতে পারে।

এটি সত্যই একই জিনিস করতে পারে। এটি না করার কারণটি হ'ল পপড উপাদানটি ফিরিয়ে দেওয়া পপ ব্যতিক্রমগুলির উপস্থিতিতে অনিরাপদ (মান অনুসারে ফিরে আসতে হবে এবং এইভাবে একটি অনুলিপি তৈরি করে)।

এই দৃশ্যের বিষয়টি বিবেচনা করুন (একটি নির্দোষ / পপ বাস্তবায়নের সাথে, আমার বক্তব্যকে অসম্পূর্ণ করতে):

template<class T>
class queue {
    T* elements;
    std::size_t top_position;
    // stuff here
    T pop()
    {
        auto x = elements[top_position];
        // TODO: call destructor for elements[top_position] here
        --top_position;  // alter queue state here
        return x;        // calls T(const T&) which may throw
    }

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

যখন আপনার পপড মান প্রয়োজন হয় না তখন এই বাস্তবায়নটিও অকার্যকর (যেমন এটি উপাদানটির একটি অনুলিপি তৈরি করে যা কেউ ব্যবহার করবে না)।

এটি দুটি পৃথক অপারেশন ( void popএবং const T& front()) সহ নিরাপদে এবং দক্ষতার সাথে প্রয়োগ করা যেতে পারে ।



37
সি ++ ১১ দ্রষ্টব্য: টি-তে যদি কোনও সস্তা নয়েসভেটস মুভ-কনস্ট্রাক্টর থাকে (যা প্রায়শই স্ট্যাকের ধরণের জিনিসগুলির ক্ষেত্রে ঘটে থাকে) তবে মান দ্বারা প্রত্যাবর্তন দক্ষ এবং ব্যতিক্রম-নিরাপদ।
রোমান এল

9
@ ডেভিডরোড্রিগিজ-ড্রিবিয়াস: আমি কোনও পরিবর্তন প্রস্তাব দিচ্ছি না, আমার বক্তব্যটি উল্লেখ করা কিছু অসুবিধা সি ++ 11 এর সাথে ইস্যুতে কম হয়ে গেছে।
রোমান এল

11
তবে কেন বলা হয় pop? এটি বেশ পাল্টা স্বজ্ঞাত। এটি নামকরণ করা যেতে পারে drop, এবং এটি প্রত্যেকের জন্য পরিষ্কার যে এটি উপাদানটি পপ করে না, বরং এর পরিবর্তে ফেলে দেয় ...
ইউলিডিশওয়ার্ট

12
@ ইউটিপিস্টিম: ডি-ফ্যাক্টো "পপ" অপারেশনটি সর্বদা একটি স্ট্যাক থেকে শীর্ষ উপাদানটি নিয়ে এটি ফিরিয়ে আনা হয়। আমি যখন প্রথম STL স্ট্যাকগুলি জুড়ে এসেছিল আমি বিস্মিত হয়ে অন্তত বলতে প্রায় popকিছুই ফিরে না। উইকিপিডিয়ায় উদাহরণস্বরূপ দেখুন ।
ক্রিস লুয়েংগো

34

আপনার লিঙ্কযুক্ত পৃষ্ঠাটি আপনার প্রশ্নের উত্তর দেয়।

পুরো বিভাগটি প্রাসঙ্গিক উদ্ধৃতি:

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

সি ++ প্রোগ্রামারকে কতগুলি কোডের কোড লিখতে হবে তার সংখ্যা নির্ধারণ করে দক্ষতার সাথে ডিজাইন করা হয়েছে।


16
সম্ভবত, তবে আসল কারণটি হ'ল কোনও সংস্করণ popযার কোনও মূল্য ফেরত দেয় তার ব্যতিক্রম নিরাপদ সংস্করণ (দৃ guarantee় গ্যারান্টি সহ) প্রয়োগ করা অসম্ভব ।
জেমস কানজে

5

পপ অপসারণ করা মানটির কোনও রেফারেন্স ফিরিয়ে দিতে পারে না, কারণ এটি ডেটা কাঠামো থেকে সরানো হচ্ছে, তাই রেফারেন্সটি কী উল্লেখ করা উচিত? এটি মান অনুসারে ফিরে আসতে পারে, তবে যদি পপের ফলাফল কোথাও সংরক্ষণ করা হয় না? তারপরে সময়টি অপ্রয়োজনে মানটি অনুলিপি করা হয়।


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

1
এই উদ্বেগটি কি এখনও কোনও নয়েসেপ্ট মুভ কনস্ট্রাক্টরের সাথে প্রয়োগ হয়? (অবশ্যই 0 টি অনুলিপি দুটি কার্যকর যে আরও কার্যকর, কিন্তু এটি একটি ব্যতিক্রম নিরাপদ, কার্যকরী সম্মিলিত ফ্রন্ট + পপ জন্য দরজা খুলতে পারে)
পেপ

1
@ পেপ্প, যদি আপনি জানেন যে value_typeনোথ্রো মুভ কনস্ট্রাক্টর রয়েছে তবে আপনি মান দ্বারা ফিরে আসতে পারেন , তবে কুই ইন্টারফেসটি আপনি এতে কোন ধরণের অবজেক্টটি সংরক্ষণ করেন তার উপর নির্ভর করে ভিন্ন হবে, যা সহায়ক হবে না।
জোনাথন ওয়াকলি

1
@ পেপ্প: এটি নিরাপদ হবে, তবে স্ট্যাকটি একটি জেনেরিক লাইব্রেরি ক্লাস এবং অতএব এটির উপাদানটি যত কম দরকারী তা সম্পর্কে তত বেশি ধারণা করতে হবে।
জন

আমি জানি যে এসটিএল এটির জন্য অনুমতি দেবে না, তবে এর অর্থ হ'ল ব্ল্যাকজ্যাক এবং feature ডাব্লু ^ ডাব্লু ^ ডব্লু এই বৈশিষ্ট্যটি দিয়ে নিজের কাত্রে শ্রেণি তৈরি করতে পারে :)
পেপ

3

বর্তমান বাস্তবায়নের সাথে, এটি বৈধ:

int &result = myqueue.front();
std::cout << result;
myqueue.pop();

যদি পপ এই জাতীয় রেফারেন্স দেয় তবে:

value_type& pop();

তাহলে নিম্নলিখিত কোডটি ক্র্যাশ হতে পারে, যেহেতু রেফারেন্সটি আর বৈধ নয়:

int &result = myqueue.pop();
std::cout << result;

অন্যদিকে, যদি এটি সরাসরি কোনও মান ফেরত দেয়:

value_type pop();

তারপরে এই কোডটি কার্যকর করার জন্য আপনার একটি অনুলিপি করা দরকার যা কম দক্ষ:

int result = myqueue.pop();
std::cout << result;

1

সি ++ 11 থেকে শুরু করে মুভি শব্দার্থক ব্যবহার করে পছন্দসই আচরণ সংরক্ষণাগারভুক্ত করা সম্ভব হবে। ভালো লেগেছে pop_and_move। সুতরাং অনুলিপি কন্সট্রাক্টরকে ডাকা হবে না এবং কার্য সম্পাদন কেবলমাত্র মুভ কনস্ট্রাক্টরের উপর নির্ভর করবে।


2
না, শব্দার্থিক স্থানান্তর যাদুকরভাবে popব্যতিক্রম নিরাপদ করে না
এলএফ

0

আপনি সম্পূর্ণরূপে এটি করতে পারেন:

std::cout << ' ' << myqueue.front();

অথবা, আপনি যদি ভেরিয়েবলের মান চান তবে একটি রেফারেন্স ব্যবহার করুন:

const auto &result = myqueue.front();
if (result > whatever) do_whatever();
std::cout << ' ' << result;

তার পরে: 'আরও বোধগম্য' শব্দটি 'আমরা ব্যবহারের নিদর্শনগুলিতে দেখেছি এবং বিভাজনের জন্য আরও প্রয়োজনীয়তা পেয়েছি' এর একটি বিষয়গত রূপ। (বিশ্রামের আশ্বাস: সি ++ ভাষা হালকাভাবে বিকশিত হচ্ছে না ...)


0

আমি মনে করি সবচেয়ে ভাল সমাধানটি হ'ল এর মতো কিছু যুক্ত করা

std::queue::pop_and_store(value_type& value);

যেখানে মান পপড মান পাবেন।

সুবিধাটি হ'ল এটি মুভ অ্যাসাইনমেন্ট অপারেটর ব্যবহার করে প্রয়োগ করা যেতে পারে, যখন ফ্রন্ট + পপ ব্যবহার করে একটি অনুলিপি তৈরি করা হয়।

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