<< a ++ << a ;? এর জন্য সঠিক উত্তর কী?


98

সম্প্রতি একটি সাক্ষাত্কারে নিম্নলিখিত উদ্দেশ্যমূলক প্রশ্ন ছিল।

int a = 0;
cout << a++ << a;

উত্তর:

ক। 10
খ। 01
গ। অপরিবর্তিত আচরণ

আমি পছন্দ করলাম উত্তর, অর্থাৎ আউটপুট "01" হবে।

তবে আমার অবাক হওয়ার পরে পরে আমাকে একজন সাক্ষাত্কারকারীর দ্বারা বলা হয়েছিল যে সঠিক উত্তরটি সি সি: অপরিজ্ঞাত।

এখন, আমি সি ++ এর সিকোয়েন্স পয়েন্টগুলির ধারণাটি জানি। আচরণটি নিম্নলিখিত বিবৃতিটির জন্য অপরিবর্তিত:

int i = 0;
i += i++ + i++;

কিন্তু আমার বিবৃতি জন্য বুঝতে অনুযায়ী cout << a++ << a, ostream.operator<<()দুইবার প্রথম সাথে কল করা হবে, ostream.operator<<(a++)এবং পরবর্তী ostream.operator<<(a)।

আমি ভিএস 2010 সংকলকটিতে ফলাফলও পরীক্ষা করেছিলাম এবং এর ফলাফলও '01' is


30
আপনি কোন ব্যাখ্যা চেয়েছিলেন? আমি প্রায়শই সম্ভাব্য প্রার্থীদের সাক্ষাত্কার নিয়ে থাকি এবং প্রশ্নগুলি পেতে আগ্রহী, এটি আগ্রহ দেখায়।
— ব্র্যাডি

4
@ জ্রোক এটি নির্ধারিত আচরণ। বাস্তবায়নের মাধ্যমে যে কোনও কিছুই করা (আপনার নামে আপনার বসকে অপমানজনক ইমেল প্রেরণ সহ) সম্মতিযুক্ত।
— জেমস কানজে

4
এই প্রশ্নটি সি ++ 11 (সি ++ এর বর্তমান সংস্করণ) উত্তরের জন্য চিৎকার করছে যা সিকোয়েন্স পয়েন্টগুলি উল্লেখ করে না। দুর্ভাগ্যক্রমে আমি সি ++ 11 এর সিকোয়েন্স পয়েন্টগুলির প্রতিস্থাপন সম্পর্কে যথেষ্ট জ্ঞাত নই।
— সিবি বেইলি

4
যদি এটি অপরিজ্ঞাত না হয় তবে এটি অবশ্যই নাও হতে পারে 10, এটি হয় হয় 01বা হয় 00। ( c++সবসময় মান মূল্যায়ন করবে cছিল আগে বৃদ্ধি হচ্ছে)। এবং এটি অপরিবর্তিত না থাকলেও এটি মারাত্মক বিভ্রান্তিকর হবে।
— ই

4
ইয়া জানেন, আমি যখন "কোট << সি ++ << সি" শিরোনামটি পড়ি তখন আমি মুহুর্তে একে সি এবং সি ++ ভাষার মধ্যে সম্পর্ক এবং "কাউট" নামে আরও কিছু ব্যক্তির বক্তব্য হিসাবে মনে করি। আপনি কি জানেন যে কেউ কীভাবে বলছিল যে তারা কীভাবে মনে করেছিল যে "কোট" সি ++ এর চেয়ে অনেক নিকৃষ্ট, এবং সি ++ সি এর চেয়ে অনেক নিকৃষ্ট ছিল - এবং সম্ভবত সংক্রমণের দ্বারা যে "কোট" সি এর চেয়ে খুব নিকৃষ্ট ছিল :)
— tchrist

উত্তর:


145

আপনি চিন্তা করতে পারেন:

cout << a++ << a;

যেমন:

std::operator<<(std::operator<<(std::cout, a++), a);

সি ++ গ্যারান্টি দেয় যে পূর্ববর্তী মূল্যায়নের সমস্ত পার্শ্ব প্রতিক্রিয়া ক্রম বিন্দুতে সম্পাদিত হবে । ফাংশন আর্গুমেন্ট মূল্যায়নের মধ্যে কোনও সিকোয়েন্স পয়েন্ট নেই যার অর্থ যুক্তির aআগে std::operator<<(std::cout, a++)বা পরে যুক্তির মূল্যায়ন করা যেতে পারে । সুতরাং উপরের ফলাফলটি অপরিজ্ঞাত।


সি ++ 17 আপডেট

সি ++ 17 এ নিয়ম আপডেট করা হয়েছে। নির্দিষ্টভাবে:

একটি শিফট অপারেটর এক্সপ্রেশন E1<<E2এবং E1>>E2, প্রতিটি মান গণনা এবং পার্শ্ব-প্রভাব E1প্রতিটি মান গণনা এবং এর পার্শ্ব প্রতিক্রিয়া আগে ক্রমযুক্ত হয় E2।

যার অর্থ এটি ফলাফলের জন্য কোডের প্রয়োজন b, যা ফলাফল দেয় 01।

দেখুন কথ্য সি ++ জন্য P0145R3 বিশোধক এক্সপ্রেশন মূল্যায়ন অর্ডার আরো বিস্তারিত জানার জন্য।


@ ম্যাক্সিম: ব্যাখ্যার জন্য ধন্যবাদ। আপনি যে কলগুলি কাটিয়েছেন তার সাথে এটি হবে সংজ্ঞায়িত আচরণ। তবে এখন, আমার কাছে আরও একটি প্রশ্ন রয়েছে (সিলার একটি হতে পারে, এবং আমি মৌলিক কিছু অনুভব করছি এবং জোরে চিন্তা করছি) আপনি কীভাবে অনুমান করলেন যে স্ট্যান্ড :: অপারেটর << () এর গ্লোবাল সংস্করণ ostream :: অপারেটর <এর পরিবর্তে ডাকা হবে < <() সদস্য সংস্করণ। ডিবাগিংয়ের সময় আমি অস্ট্রিম :: অপারেটর << () কলটির একটি সংস্করণে বৈশ্বিক সংস্করণ না থেকে নামছি এবং এ কারণেই প্রাথমিকভাবে আমি ভেবেছিলাম যে উত্তরটি হবে 01
— প্রাইভেটস

@ ম্যাক্সিম এটি আলাদা করে তোলে তা নয়, তবে যেহেতু cটাইপ রয়েছে intতাই operator<<এখানে সদস্য ফাংশন রয়েছে।
— জেমস কানজে

4
@ প্রভা: operator<<সদস্য ফাংশন বা একটি ফ্রি-স্ট্যান্ডিং ফাংশন সিকোয়েন্স পয়েন্টগুলিকে প্রভাবিত করে না।
— ম্যাক্সিম এগারুশকিন

11
'সিকোয়েন্স পয়েন্ট' আর সি ++ স্ট্যান্ডার্ডে ব্যবহৃত হয় না। এটি অনর্থক ছিল এবং সম্পর্কের পরে 'সিকোয়েন্সড / সিক্যুয়েন্সড' পরে প্রতিস্থাপন করা হয়েছে।
— রাফা ডগির্ড

4
So the result of the above is undefined.তোমার ব্যাখ্যা শুধুমাত্র জন্য ভাল অনির্দিষ্ট , না অনির্ধারিত । JamesKanze ব্যাখ্যা কিভাবে এটি আরো প্রাণনাশক undefined তার উত্তর যদিও মধ্যে ।
— উত্সাহক

68

প্রযুক্তিগতভাবে, সামগ্রিকভাবে এটি অনির্ধারিত আচরণ ।

তবে, উত্তরের দুটি গুরুত্বপূর্ণ দিক রয়েছে।

কোড বিবৃতি:

std::cout << a++ << a;

হিসাবে মূল্যায়ন করা হয়:

std::operator<<(std::operator<<(std::cout, a++), a);

মান কোনও ক্রিয়ায় আর্গুমেন্টের মূল্যায়নের ক্রম সংজ্ঞায়িত করে না।
সুতরাং হয়:

  • std::operator<<(std::cout, a++) প্রথমে মূল্যায়ন করা হয় বা
  • aপ্রথমে মূল্যায়ন করা হয় বা
  • এটি কোনও বাস্তবায়ন সংজ্ঞায়িত আদেশ হতে পারে।

এই অর্ডারটি অনির্ধারিত [রেফ 1] ।

[রেফার 1] সি ++ 03 5.2.2 ফাংশন কল করুন
প্যারা 8

যুক্তিগুলির মূল্যায়নের ক্রমটি অনির্ধারিত । ফাংশন প্রবেশের আগে যুক্তি প্রকাশের মূল্যায়নের সমস্ত পার্শ্ব প্রতিক্রিয়া কার্যকর হয়। পোস্টফিক্স এক্সপ্রেশন এবং আর্গুমেন্ট এক্সপ্রেশন তালিকার মূল্যায়নের ক্রমটি অনির্দিষ্ট।

আরও একটি ফাংশনে আর্গুমেন্টের মূল্যায়নের মধ্যে কোনও সিকোয়েন্স পয়েন্ট নেই তবে সমস্ত আর্গুমেন্ট [রেফ 2] এর মূল্যায়ন করার পরেই একটি সিকোয়েন্স পয়েন্ট বিদ্যমান ।

[রেফ 2) সি ++ 03 1.9 প্রোগ্রাম কার্যকরকরণ [অন্তঃসারণ]:
অনুচ্ছেদ 17:

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

মনে রাখবেন যে, এখানে মান cহ'ল কোনও হস্তক্ষেপের ক্রম বিন্দু ছাড়াই একাধিকবার অ্যাক্সেস করা হচ্ছে, এ সম্পর্কে মানটি বলে:

[রেফ 3) সি ++ 03 5 এক্সপ্রেশন [এক্সপ্রেস]:
প্যারা 4:

....
পূর্ববর্তী এবং পরবর্তী সিকোয়েন্স পয়েন্টের মধ্যে একটি স্কেলার অবজেক্টের তার সঞ্চিত মানটি একবারে প্রকাশের মূল্যায়নের মাধ্যমে একবারে পরিবর্তিত হবে। তদ্ব্যতীত, পূর্বের মানটি কেবলমাত্র সংরক্ষণ করা হবে তা নির্ধারণের জন্য অ্যাক্সেস করা উচিত । এই অনুচ্ছেদে প্রয়োজনীয়তাগুলি একটি সম্পূর্ণ অভিব্যক্তিটির subexpresstions প্রতিটি অনুমতিযোগ্য ক্রম জন্য পূরণ করা হবে; অন্যথায় আচরণটি সংজ্ঞায়িত ।

কোডটি cসিকোয়েন্স পয়েন্টকে হস্তক্ষেপ না করে একাধিকবার সংশোধন করে এবং সঞ্চিত বস্তুর মান নির্ধারণের জন্য এটি অ্যাক্সেস করা হচ্ছে না। এই উপরে দফা সুস্পষ্ট লঙ্ঘন এবং অত: পর ফলে মান দ্বারা বাধ্যতামূলক হয় অনির্ধারিত আচরণ [সূত্র 3] ।


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

4
@ সব হ্যাঁ আমি আপনার সম্পাদনাগুলি দেখিনি (যদিও আমি জোকের বক্তব্যটির প্রতিক্রিয়া জানিয়েছিলাম যে প্রোগ্রামটি কিছু অদ্ভুত কিছু করতে পারে না --- এটি পারে)। আপনার সম্পাদিত সংস্করণ যতদূর যায় ভাল, তবে আমার মনে, মূল শব্দটি আংশিক ক্রম ; সিকোয়েন্স পয়েন্টগুলি কেবল একটি আংশিক ক্রম প্রবর্তন করে।
— জেমস কানজে

4
একটি বিস্তৃত বিবরণের জন্য @ সমস্ত ধন্যবাদ, সত্যিই খুব সহায়ক !!
— pravs

4
নতুন সি ++ 0 এক্স স্ট্যান্ডার্ড মূলত একই কথা বলেছে তবে বিভিন্ন বিভাগে এবং বিভিন্ন শব্দার্থে :) উদ্ধৃতি: (1.9 প্রোগ্রাম এক্সিকিউশন [অন্তঃসংশ্লিষ্টতা], পার 15): "যদি কোনও স্কেলার অবজেক্টের উপরের পার্শ্ব প্রতিক্রিয়াটি আপেক্ষিক না হয় হয় একই স্কেলার অবজেক্টের অন্য কোনও পার্শ্ব প্রতিক্রিয়া বা একই স্কেলার অবজেক্টের মান ব্যবহার করে একটি মান গণনা, আচরণটি হ্রাস করা হয় না ""
— রাফা ডাউগার্ড

4
আমি বিশ্বাস করি এই উত্তরে একটি ত্রুটি রয়েছে। "std :: cout << সি ++ << গ;" "std :: অপারেটর << (std :: অপারেটর << (std :: cout, c ++), c)" তে অনুবাদ করতে পারবেন না, কারণ std :: অপারেটর << (std :: ostream &, int) এর অস্তিত্ব নেই। পরিবর্তে, এটি "std :: cout.operator << (c ++)। অপারেটর (c);" এ অনুবাদ করে, যা আসলে "c ++" এবং "c" এর মূল্যায়নের মধ্যে একটি ক্রম বিন্দু (একটি ওভারলোডেড অপারেটর হিসাবে বিবেচিত হয়) ফাংশন কল এবং সেইজন্য একটি ক্রম পয়েন্ট থাকে যখন ফাংশন কল ফিরে আসে)। ফলে আচরণ ও মৃত্যুদন্ড অর্ডার হয় নির্দিষ্ট করা হয়েছে।
— ক্রিস্টোফার স্মিথ

20

সিকোয়েন্স পয়েন্টগুলি কেবল একটি আংশিক ক্রম সংজ্ঞায়িত করে । আপনার ক্ষেত্রে, আপনার একবার (ওভারলোড রেজোলিউশন হয়ে গেলে):

std::cout.operator<<( a++ ).operator<<( a );

এর মধ্যে একটি ক্রম বিন্দু নেই a++এবং প্রথম কল std::ostream::operator<<, এবং দ্বিতীয় মধ্যে একটি ক্রম বিন্দু আছে aএবং দ্বিতীয় কল std::ostream::operator<<, কিন্তু মধ্যে কোনো ক্রম বিন্দু a++এবং a; কেবলমাত্র আদেশের সীমাবদ্ধতাগুলি হ'ল a++প্রথম কল করার আগে পুরোপুরি মূল্যায়ন (পার্শ্ব প্রতিক্রিয়া সহ) operator<<এবং aদ্বিতীয় কল করার আগে দ্বিতীয়টি সম্পূর্ণ মূল্যায়ন করা operator<<। (কার্য্যক্রমিক ক্রম সীমাবদ্ধতাগুলিও রয়েছে: দ্বিতীয় কলটি operator<<প্রথমটির আগে আসতে পারে না, কারণ এটি আর্গুমেন্ট হিসাবে প্রথমটির ফলাফলের প্রয়োজন)) §5 / 4 (সি ++ 03) বলেছেন:

যেখানে উল্লিখিত হয়েছে ব্যতীত পৃথক অপারেটরগুলির অপারেশনগুলির মূল্যায়নের ক্রম এবং স্বতন্ত্র এক্সপ্রেশনগুলির subexpressions এবং যে ক্রমে পার্শ্ব প্রতিক্রিয়া হয় সেটিকে নির্ধারিত। পূর্ববর্তী এবং পরবর্তী সিকোয়েন্স পয়েন্টের মধ্যে একটি স্কেলার অবজেক্টের তার সঞ্চিত মানটি একবারে অভিব্যক্তির মূল্যায়নের মাধ্যমে একবারে পরিবর্তিত হবে। তদ্ব্যতীত, পূর্বের মানটি কেবলমাত্র সংরক্ষণ করা হবে তা নির্ধারণের জন্য অ্যাক্সেস করা উচিত। এই অনুচ্ছেদের প্রয়োজনীয়তা একটি সম্পূর্ণ এক্সপ্রেশন এর subexpresstions প্রতিটি অনুমতিযোগ্য ক্রম জন্য পূরণ করা হবে; অন্যথায় আচরণটি সংজ্ঞায়িত।

আপনার মত প্রকাশের মঞ্জুরিযোগ্য orderings মধ্যে একজন হল a++, a, এর প্রথম কল operator<<করার পরে, দ্বিতীয় কল operator<<; এটি a( a++) এর সঞ্চিত মানটি সংশোধন করে এবং নতুন মান (দ্বিতীয় a) নির্ধারণ করা ব্যতীত অন্যকে এটি অ্যাক্সেস করে , আচরণটি সংজ্ঞায়িত।


আপনার মানটির উদ্ধৃতি থেকে একটি ধরা। আইআইআরসি ওভারলোডেড অপারেটরের সাথে কথা বলার সময় "ব্যতীত যেখানে উল্লেখ করা হয়েছে" এর মধ্যে একটি ব্যতিক্রম অন্তর্ভুক্ত রয়েছে, যা অপারেটরটিকে একটি ফাংশন হিসাবে বিবেচনা করে এবং সুতরাং প্রথম এবং দ্বিতীয় কলটির মধ্যে একটি স্ট্যান্ড :: ostream :: অপারেটরের << (int) তৈরি করে )। আমি ভুল হলে আমাকে সংশোধন করুন।
— ক্রিস্টোফার স্মিথ

@ ক্রিস্টোফারস্মিথ একটি ওভারলোডেড অপারেটর কোনও ফাংশন কলের মতো আচরণ করে। পরিবর্তে cকোনও সংজ্ঞায়িত ব্যবহারকারীর সাথে যদি কোনও ব্যবহারকারীর ধরন হয় তবে তার ফলাফলগুলি অনির্ধারিত হবে, তবে কোনও সংজ্ঞায়িত আচরণ থাকবে না। ++int
— জেমস কানজে

4
@ChristopherSmith যদি তাদের মধ্যে সম্পর্কচ্ছেদ ক্রম বিন্দু কোথায় দেখতে পাচ্ছ cমধ্যে foo(foo(bar(c)), c)? ফাংশনগুলি ডাকা হয় এবং কখন ফিরে আসে সেগুলির একটি সিকোয়েন্স পয়েন্ট রয়েছে তবে দুটির মূল্যায়নের মধ্যে কোনও ফাংশন কলের প্রয়োজন নেই c।
— জেমস কানজে

4
@ChristopherSmith যদি cএকটি UDT, ওভারলোড অপারেটার ছিল হবে ফাংশান কল করা, এবং একটি ক্রম বিন্দু পরিচয় করিয়ে দিতে হবে, তাই আচরণ অনির্দিষ্ট হওয়া যাবে। তবে সাব-এক্সপ্রেশনটি cআগে বা পরে মূল্যায়ন করা হয়েছিল কিনা তা এখনও অনির্দিষ্ট করা হবে c++, সুতরাং আপনি বর্ধিত সংস্করণ পেয়েছেন কিনা তা নির্দিষ্ট করা হয়নি (এবং তাত্ত্বিকভাবে, প্রতিটি সময় একই হতে হবে না)।
— জেমস কানজে

4
@ ক্রিসটফারস্মিথ সিক্যুয়েন্স পয়েন্টের আগে সবকিছুই সিক্যুয়েন্স পয়েন্টের পরে কিছু ঘটবে। তবে সিকোয়েন্স পয়েন্টগুলি কেবল একটি আংশিক ক্রম সংজ্ঞায়িত করে। প্রশ্নের মত প্রকাশের ক্ষেত্রে, উদাহরণস্বরূপ, উপ-এক্সপ্রেশনগুলির মধ্যে কোনও ক্রম বিন্দু নেই cএবং c++তাই দুটি কোনও ক্রমে ঘটতে পারে। সেমিকোলন হিসাবে ... তারা সম্পূর্ণ এক্সপ্রেশন হিসাবে কেবলমাত্র এটি একটি ক্রম বিন্দুর কারণ ঘটায়। অন্যান্য গুরুত্বপূর্ণ ক্রম পয়েন্ট ফাংশন কল আছেন: f(c++)বৃদ্ধি দেখতে হবে cমধ্যে f, এবং কমা অপারেটর, &&, ||এবং ?:এছাড়াও ক্রম পয়েন্ট কারণ।
— জেমস কানজে

4

সঠিক উত্তরটি প্রশ্নটি করা question বিবৃতিটি অগ্রহণযোগ্য কারণ কোনও পাঠক সুস্পষ্ট উত্তর দেখতে পাচ্ছেন না। এটি দেখার আরেকটি উপায় হ'ল আমরা পার্শ্ব-প্রতিক্রিয়া (সি ++) প্রবর্তন করেছি যা বিবৃতিটি ব্যাখ্যা করতে আরও শক্ত করে তোলে। সংক্ষিপ্ত কোডটি দুর্দান্ত, এর অর্থ পরিষ্কার করে দেওয়া।


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