নরটার্নের বিন্দু কী?


189

[dcl.attr.noreturn] নিম্নলিখিত উদাহরণ সরবরাহ করে:

[[ noreturn ]] void f() {
    throw "error";
    // OK
}

তবে এর বিন্দুটি কী তা আমি বুঝতে পারি না [[noreturn]], কারণ ফাংশনের রিটার্ন টাইপ ইতিমধ্যে void

সুতরাং, noreturnগুণাবলীর বিন্দুটি কী ? কীভাবে এটি ব্যবহার করার কথা?


1
এই ধরণের ফানসিটনের সম্পর্কে কী এত গুরুত্বপূর্ণ (এটি সম্ভবত কোনও প্রোগ্রামের প্রয়োগে একবার ঘটবে) এমন মনোযোগের দাবি রাখে? এটি কি সহজে সনাক্তযোগ্য পরিস্থিতি নয়?
ব্যবহারকারী 666412

1
@ মিঃলিস্টার ওপি'র "প্রত্যাবর্তন" এবং "প্রত্যাবর্তন মান" এর ধারণাগুলি বিলোপ করে। তারা প্রায় সর্বদা ব্যবহারের ক্ষেত্রে কীভাবে দেওয়া হয়েছে, তা আমি মনে করি বিভ্রান্তি ন্যায়সঙ্গত।
স্লিপ ডি থম্পসন

উত্তর:


209

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

এটি সংযোজকগণ কিছু অপ্টিমাইজেশান তৈরি করতে এবং আরও ভাল সতর্কতা তৈরি করতে ব্যবহার করতে পারেন। উদাহরণস্বরূপ যদি fনোরটারন অ্যাট্রিবিউট থাকে তবে সংকলক g()আপনাকে লিখতে গিয়ে ডেড কোড হওয়ার বিষয়ে সতর্ক করতে পারে f(); g();। একইভাবে সংকলক জানতে চাইবে যে আপনাকে কল করার পরে ফিরে আসা বিবৃতিগুলি সম্পর্কে সতর্ক করতে হবে না f()


5
এমন কোনও ফাংশন সম্পর্কে কী execveযে ফিরে আসা উচিত নয় তবে পারে ? এটিতে নোরটারন অ্যাট্রিবিউট থাকা উচিত?
কালরিশ

22
না, এটি করা উচিত নয় - যদি কন্ট্রোল প্রবাহকে কলারে ফিরে যাওয়ার কোনও সম্ভাবনা থাকে, তবে এটির noreturnবৈশিষ্ট্যটি থাকা উচিত নয় । noreturnইত্যাদি উদাহরণস্বরূপ কারণ আপনার প্রস্থান (কল), পরিত্যাগ () জাহির (0), - শুধুমাত্র আপনার ফাংশন এমন কিছু বিষয় যা নিয়ন্ত্রণ প্রবাহ সামনে কর্মসূচি বন্ধ আহ্বানকারী ফিরে আসতে পারেন না নিশ্চিত করা হয় যদি ব্যবহার করা যেতে পারে
RavuAlHemio

6
@ স্লিপডি.টম্পসন যদি কোনও নরটার্ন ফাংশনটির কল একটি ট্রাই-ব্লকে মুড়ে ফেলা হয়, তবে ক্যাচ ব্লক থেকে পাওয়া কোনও কোডই আবার অ্যাক্সেসযোগ্য হিসাবে গণ্য হবে।
sepp2k

2
@ sepp2k কুল সুতরাং এটি ফিরে আসা অসম্ভব, কেবল অস্বাভাবিক। এটি দরকারী। চিয়ার্স।
স্লিপ ডি থম্পসন

7
@ স্লিপডি.টমসন না, ফিরে আসা অসম্ভব। নিক্ষেপ একটি ব্যতিক্রম নাই, তাই যদি যে পথ ছোঁড়ার তারপর এটা noreturn। ব্যতিক্রমটিকে পরিচালনা করা এটি ফিরে আসার মতো নয়। tryকল করার পরে যে কোনও কোড এখনও অ্যাক্সেসযোগ্য এবং যদি তা না হয় voidতবে ফেরতের মূল্যের কোনও অ্যাসাইনমেন্ট বা ব্যবহার ঘটবে না।
জন হান্না

62

noreturnসংকলককে বলে না যে ফাংশনটি কোনও মান দেয় না। এটি সংকলককে বলে যে নিয়ন্ত্রণ প্রবাহ কলারে ফিরে আসবে না । এটি সংকলকটি বিভিন্ন রকমের অপ্টিমাইজেশান তৈরি করতে দেয় - কলটির চারপাশে কোনও অস্থির অবস্থা সংরক্ষণ এবং পুনরুদ্ধার করার দরকার নেই, এটি ডেড-কোড এমন কোনও কোড মুছে ফেলতে পারে যা অন্যথায় কল অনুসরণ করবে ইত্যাদি etc.


29

এর অর্থ এই যে ফাংশনটি সম্পূর্ণ হবে না। এই কল করার পরে নিয়ন্ত্রণ প্রবাহ কখনই বিবৃতিতে আঘাত করবে না f():

void g() {
   f();
   // unreachable:
   std::cout << "No! That's impossible" << std::endl;
}

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



4
@ টেম্পলেটআরেক্স: সংকলন করুন -Wno-returnএবং আপনি একটি সতর্কতা পাবেন। সম্ভবত আপনি যেটির প্রত্যাশা করেছিলেন তা নয় তবে এটি সম্ভবত আপনাকে জানাতেই যথেষ্ট যে সংকলকটি কী তা সম্পর্কে জ্ঞান রয়েছে [[noreturn]]এবং এটি এর সুবিধা নিতে পারে। (আমি কিছুটা অবাক হয়েছি যে -Wunreachable-codeলাথি
মারেনি

3
@ টেম্পলেটরেেক্স: দুঃখিত -Wmissing-noreturn, সতর্কবার্তাটি বোঝায় যে প্রবাহ বিশ্লেষণ নির্ধারণ করে যে এটি পৌঁছনীয় std::coutনয়। উত্পন্ন operator<<
সমাবেশটি দেখার

1
এখানে একটি অ্যাসেম্বলি ডাম্প রয়েছে (-S -o - কলিরুতে পতাকাগুলি), অবশ্যই "অপ্রচারযোগ্য" কোডটি ফেলে দেয়। আকর্ষণীয়ভাবে যথেষ্ট, -O1ইতিমধ্যে[[noreturn]] ইঙ্গিত ছাড়াই সেই অপ্রাপ্য কোডটি ফেলে দেওয়ার জন্য যথেষ্ট
TemplateRex

2
@ টেম্পলেটআরেক্স: সমস্ত কোডই একই অনুবাদ ইউনিটে এবং দৃশ্যমান, তাই সংকলক [[noreturn]]কোডটি থেকে অনুমান করতে পারে । তাহলে এই অনুবাদটি ইউনিট শুধুমাত্র ফাংশন যা অন্য কোথাও সংজ্ঞায়িত হয়েছিল ঘোষণা ছিল, কম্পাইলার যেমন নয়, যে কোড ড্রপ পারব না জানি যে ফাংশন ফেরত দেয় না। সংযোগকারীকে এই বৈশিষ্ট্যটির সাহায্য করা উচিত।
ডেভিড রদ্রিগেজ -

17

পূর্ববর্তী উত্তরগুলি সঠিকভাবে উত্তর দিয়েছিল যে নোরটার্ন কী, তবে কেন এটি বিদ্যমান নেই। আমি "অপ্টিমাইজেশন" মন্তব্যগুলি মূল উদ্দেশ্য বলে মনে করি না: যে কার্যগুলি ফিরে আসে না তা বিরল এবং সাধারণত অপ্টিমাইজ করার প্রয়োজন হয় না। বরং আমি মনে করি যে নর্থটারনের প্রধান রেসন ডি'ট্রে হ'ল মিথ্যা-ইতিবাচক সতর্কতা এড়ানো। উদাহরণস্বরূপ, এই কোডটি বিবেচনা করুন:

int f(bool b){
    if (b) {
        return 7;
    } else {
        abort();
    }
 }

যদি গর্ভপাত () "নরটার্ন" হিসাবে চিহ্নিত না হত, সংকলক এই কোডটির এমন একটি পথ থাকার বিষয়ে সতর্ক করেছিল যে যেখানে f প্রত্যাশার সাথে কোনও পূর্ণসংখ্যা ফেরত দেয় না। তবে গর্ভপাত () কোনও রিটার্ন হিসাবে চিহ্নিত না করে এটি জানেন যে কোডটি সঠিক।


অন্য সমস্ত উদাহরণ তালিকাভুক্ত অকার্যকর ফাংশন ব্যবহার করে - যখন আপনার [[কোনও প্রত্যাবর্তন]] নির্দেশনা এবং একটি অ-শূন্য রিটার্ন টাইপ থাকবে তখন কীভাবে এটি কাজ করবে? সংকলক ফিরে না আসার এবং সতর্কতাটিকে অগ্রাহ্য করার সম্ভাবনা সম্পর্কে সতর্ক করতে প্রস্তুত হয়ে গেলে কি [[কোনও প্রত্যাবর্তন]] নির্দেশনা কার্যকর হবে? উদাহরণস্বরূপ, সংকলকটি কি যায়: "ঠিক আছে, এখানে একটি অ-শূন্য ফাংশন।" * সংকলন চালিয়ে যাচ্ছে * "ওহ বাজে, এই কোডটি ফিরে না আসতে পারে! আমি কি ব্যবহারকারীকে সতর্ক করব?" "কিছু মনে নেই, আমি নো-রিটার্নের নির্দেশনা দেখছি। "
র্যালি এল।

2
আমার উদাহরণে নরটার্ন ফাংশন চ () নয়, এটি বন্ধ () ort এটি একটি অ-শূন্য ফাংশন নরটার্ন চিহ্নিত করার কোনও মানে রাখে না। এমন একটি ফাংশন যা কখনও কখনও কোনও মান দেয় এবং কখনও কখনও ফিরে আসে (একটি ভাল উদাহরণ কার্যকর করা হয়)) নরটার্ন হিসাবে চিহ্নিত করা যায় না।
নাদভ হার'এল

1
অন্তর্নিহিত-fallthrough অন্য ধরনের একটি উদাহরণ হল: stackoverflow.com/questions/45129741/...
সিরো Santilli郝海东冠状病六四事件法轮功

11

তাত্ত্বিকভাবে বলতে গেলে টাইপ করুন, voidযা অন্য ভাষায় unitবা বলা হয় top। এর যৌক্তিক সমতুল্য সত্য । কোনও মান বৈধভাবে কাস্ট করা যেতে পারে void(প্রতিটি ধরণের একটি উপপ্রকার void)। এটিকে "মহাবিশ্ব" সেট হিসাবে ভাবুন; বিশ্বের সমস্ত মানগুলির সাথে অভিন্ন কোনও ক্রিয়াকলাপ নেই , সুতরাং ধরণের মানের জন্য কোনও বৈধ ক্রিয়াকলাপ নেই void। এটিকে অন্য উপায়ে রাখুন, আপনাকে বলছেন যে মহাবিশ্বের সেটগুলির সাথে সম্পর্কিত কিছু আপনাকে কোনও তথ্য দেয় না - আপনি এটি ইতিমধ্যে জানেন। সুতরাং নিম্নলিখিতটি শব্দ:

(void)5;
(void)foo(17); // whatever foo(17) does

তবে নীচের অ্যাসাইনমেন্টটি নয়:

void raise();
void f(int y) {
    int x = y!=0 ? 100/y : raise(); // raise() returns void, so what should x be?
    cout << x << endl;
}

[[noreturn]]অন্যদিকে, কখনও কখনও বলা হয় empty, Nothing, Bottomবা Botএবং লজিক্যাল সমতূল্য মিথ্যা । এটির কোনও মূল্য নেই এবং এই ধরণের একটি এক্সপ্রেশনটি কোনও ধরণের (অর্থাত্ সাব টাইপ) )ালাই করা যেতে পারে। এটি খালি সেট। মনে রাখবেন যে কেউ যদি আপনাকে "foo () এর এক্সপ্রেশনটির মান শূন্য সেটটির সাথে সম্পর্কিত" বলে দেয় তবে এটি অত্যন্ত তথ্যপূর্ণ - এটি আপনাকে বলে যে এই অভিব্যক্তিটি কখনই তার সাধারণ সম্পাদন সম্পন্ন করবে না; এটি বাতিল, নিক্ষেপ বা স্তব্ধ হয়ে যাবে। এটি ঠিক এর বিপরীত void

সুতরাং নিম্নলিখিতটি কোনও তাত্পর্যপূর্ণ নয় (ছদ্ম-সি ++, যেহেতু noreturnপ্রথম-শ্রেণীর সি ++ টাইপ নয়)

void foo();
(noreturn)5; // obviously a lie; the expression 5 does "return"
(noreturn)foo(); // foo() returns void, and therefore returns

কিন্তু নীচের কার্যভারটি পুরোপুরি বৈধ, যেহেতু throwকম্পাইলার ফিরে না আসার বিষয়টি বোঝে:

void f(int y) {
    int x = y!=0 ? 100/y : throw exception();
    cout << x << endl;
}

নিখুঁত বিশ্বে আপনি উপরের noreturnফাংশনের রিটার্ন মান হিসাবে ব্যবহার করতে পারেন raise():

noreturn raise() { throw exception(); }
...
int x = y!=0 ? 100/y : raise();

দুঃখের বিষয়, সম্ভবত ব্যবহারিক কারণে সি ++ এটি অনুমতি দেয় না। পরিবর্তে এটি আপনাকে [[ noreturn ]]অ্যাট্রিবিউট ব্যবহার করার ক্ষমতা দেয় যা সংকলক অপ্টিমাইজেশন এবং সতর্কতাগুলিকে গাইড করতে সহায়তা করে।


5
কিছুই কাস্ট করা যেতে পারে voidএবং voidকখনো মূল্যায়ন trueবা falseবা অন্য কিছু।
ক্লিয়ারার

5
যখন আমি বলি true, আমি " trueধরণের মান" বলতে চাই না boolতবে যুক্তিবাদী অর্থে, কারি-হাওয়ার্ডের চিঠিপত্রটি দেখুন
এলাজার

8
অ্যাবস্ট্রাক্ট টাইপ থিওরি যা কোনও নির্দিষ্ট ভাষার টাইপ সিস্টেমের সাথে খাপ খায় না সেই ভাষার টাইপ সিস্টেমটি আলোচনা করার সময় অপ্রাসঙ্গিক। প্রশ্ন: প্রশ্নে :-), টাইপ তত্ত্ব নয়, সি ++ সম্পর্কিত about
ক্লিয়ারার

8
(void)true;উত্তরটি পুরোপুরি বৈধ। void(true)সিনট্যাকটিক্যালি সম্পূর্ণ আলাদা কিছু। এটি যুক্তি হিসাবে কোনও voidকনস্ট্রাক্টরকে কল করে নতুন ধরণের অবজেক্ট তৈরি করার চেষ্টা true; এটি ব্যর্থ হয়, অন্যান্য কারণে, কারণ voidপ্রথম শ্রেণি নয়।
এলাজার

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