সংজ্ঞায়িত আচরণ এবং ক্রম পয়েন্টগুলি পুনরায় লোড হয়েছে


84

এই বিষয়টিকে নিম্নলিখিত বিষয়ের একটি অনুক্রম বিবেচনা করুন:

পূর্ববর্তী কিস্তি
অনির্ধারিত আচরণ এবং ক্রম পয়েন্ট

আসুন এই মজাদার এবং সংশ্লেষিত অভিব্যক্তিটি পুনরায় ঘুরে দেখি (তাত্পর্যপূর্ণ বাক্যাংশগুলি উপরের বিষয় থেকে নেওয়া হয়েছে * হাসি *):

i += ++i;

আমরা বলি এটি অনির্ধারিত-আচরণকে আহ্বান করে। আমি অনুমান যে যখন এই বলে, আমরা পরোক্ষভাবে যে অনুমান টাইপ এর iবিল্ট-ইন ধরনের একটি।

কি হবে যদি টাইপ এর iএকটি ব্যবহারকারী-সংজ্ঞায়িত ধরনের? বলুন এর ধরণটি Indexযা এই পোস্টে পরে সংজ্ঞায়িত হয়েছে (নীচে দেখুন)। এটি কি এখনও অপরিজ্ঞাত আচরণের জন্য প্রার্থনা করবে?

যদি হ্যাঁ, কেন? এটি কি লেখার সমতুল্য নয় i.operator+=(i.operator++());এমনকি সিনট্যাক্টিক্যালি সহজ i.add(i.inc());? অথবা, তারাও কি অনির্ধারিত আচরণের ডাক দেয়?

যদি না হয় তবে কেন? সর্বোপরি, টানা ধারাবাহিক পয়েন্টগুলির মধ্যে অবজেক্টটি দু'বারi সংশোধিত হয় । অনুগ্রহ করে থাম্বের নিয়মটি স্মরণ করুন: একটি অভিব্যক্তি ধারাবাহিক "সিকোয়েন্স পয়েন্টগুলির মধ্যে একবারে একবারে কোনও জিনিসের মান পরিবর্তন করতে পারে And এবং যদি i += ++iএকটি অভিব্যক্তি হয় তবে অবশ্যই এটি অপরিজ্ঞাত আচরণের জন্য প্রার্থনা করবে If যদি তাই হয় তবে এর সমতুল্য i.operator+=(i.operator++());এবং i.add(i.inc());অবশ্যই অপরিবর্তিত আচরণের জন্য প্রার্থনা করতে হবে" অসত্য বলে মনে হচ্ছে! (যতদূর আমি বুঝতে পারি)

বা, i += ++iএকটি অভিব্যক্তি দিয়ে শুরু হয় না? যদি তাই হয় তবে তা কী এবং ভাবের সংজ্ঞা কী ?

যদি একটি অভিব্যক্তি, এবং একই সময়ে তার আচরণ এছাড়াও ভালভাবে সংজ্ঞায়িত, তাহলে এটি যে বোঝা একটি অভিব্যক্তি সঙ্গে যুক্ত ক্রম বিন্দুর সংখ্যা একরকম উপর নির্ভর করে টাইপ অভিব্যক্তি জড়িত operands করুন। আমি কি সঠিক (এমনকি আংশিক)?


যাইহোক, কিভাবে এই অভিব্যক্তি সম্পর্কে?

//Consider two cases:
//1. If a is an array of a built-in type
//2. If a is user-defined type which overloads the subscript operator!

a[++i] = i; //Taken from the previous topic. But here type of `i` is Index.

আপনার প্রতিক্রিয়াতে আপনাকে এটি অবশ্যই বিবেচনা করতে হবে (যদি আপনি এটির আচরণটি নিশ্চিতভাবে জানেন তবে)। :-)


হয়

++++++i;

সি ++ 03 তে ভাল সংজ্ঞায়িত? সর্বোপরি, এটি এই,

((i.operator++()).operator++()).operator++();

class Index
{
    int state;

    public:
        Index(int s) : state(s) {}
        Index& operator++()
        {
            state++;
            return *this;
        }
        Index& operator+=(const Index & index)
        {
            state+= index.state;
            return *this;
        }
        operator int()
        {
            return state;
        }
        Index & add(const Index & index)
        {
            state += index.state;
            return *this;
        }
        Index & inc()
        {
            state++;
            return *this;
        }
};

13
+1 দুর্দান্ত প্রশ্ন, যা দুর্দান্ত উত্তরে অনুপ্রাণিত করেছে। আমার মনে হয় আমার বলার দরকার আছে যে এটি এখনও ভয়ঙ্কর কোড যা আরও বেশি পঠনযোগ্য হওয়ার জন্য রিফ্যাক্টর করা উচিত, তবে আপনি সম্ভবত জানেন যে :)
ফিলিপ পটার

4
@ প্রশ্নটি কী: কে বলেছে যে এটি একই? বা কে বলেছে যে এটি এক নয়? আপনি কীভাবে এগুলি প্রয়োগ করেন তার উপর নির্ভর করে না? (দ্রষ্টব্য: আমি ধরণের ধরণটি sব্যবহারকারী-সংজ্ঞায়িত প্রকারের
নওয়াজ

4
আমি দুটি সিকোয়েন্স পয়েন্টের মধ্যে কোনও স্কেলার অবজেক্টটি দু'বার সংশোধিত হতে দেখছি না ...
জোহানেস স্কাউব - লিটব

4
@ জোহানেস: তারপরে এটি স্কেলার অবজেক্ট সম্পর্কে । এটা কি? আমি অবাক হয়েছি কেন আগে আমি এর আগে শুনিনি। হতে পারে, কারণ টিউটোরিয়ালগুলি / সি ++ - এফএকিউগুলি উল্লেখ করে না, বা জোর দেয় না? এটি বিল্ট-ইন টাইপের অবজেক্টগুলির থেকে পৃথক ?
নওয়াজ

4
@ ফিলিপ: অবশ্যই, আমি বাস্তব জীবনে এই জাতীয় কোড লিখব না; আসলে, কোন বুদ্ধিমান প্রোগ্রামার এটি লিখতে যাচ্ছে না। এই প্রশ্নগুলি সাধারণত তৈরি করা হয় যাতে আমরা অপরিজ্ঞাত-আচরণ এবং ক্রম পয়েন্টগুলির পুরো ব্যবসায়টি আরও ভালভাবে বুঝতে পারি! :-)
নওয়াজ

উত্তর:


48

এটি কোড মত দেখাচ্ছে

i.operator+=(i.operator ++());

সিকোয়েন্স পয়েন্টগুলির সাথে পুরোপুরি সূক্ষ্ম কাজ করে। সি ++ আইএসও স্ট্যান্ডার্ডের বিভাগ 1.9.17 সিকোয়েন্স পয়েন্ট এবং ফাংশন মূল্যায়ন সম্পর্কে এটি বলে:

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

এটি উদাহরণস্বরূপ নির্দেশ করবে যে i.operator ++()প্যারামিটার হিসাবে operator +=তার মূল্যায়নের পরে ক্রম বিন্দু রয়েছে। সংক্ষেপে, ওভারলোডেড অপারেটরগুলি ফাংশন হওয়ায় সাধারণ সিকোয়েন্সিং বিধি প্রযোজ্য।

দুর্দান্ত প্রশ্ন, যাই হোক! আমি সত্যিই পছন্দ করি যে আপনি কীভাবে আমাকে এমন একটি ভাষার সমস্ত সংক্ষিপ্ত বিবরণ বুঝতে বাধ্য করছেন যা আমি ইতিমধ্যে ভেবেছিলাম আমি জানি (এবং ভেবেছিলাম যে আমি জানি যে আমি জানি)। :-)


12

http://www.eelis.net/C++/anologliterals.xhtml অ্যানালগ আক্ষরিকাগুলি আমার মনে আসে

  unsigned int c = ( o-----o
                     |     !
                     !     !
                     !     !
                     o-----o ).area;

  assert( c == (I-----I) * (I-------I) );

  assert( ( o-----o
            |     !
            !     !
            !     !
            !     !
            o-----o ).area == ( o---------o
                                |         !
                                !         !
                                o---------o ).area );

একটি প্রশ্ন ছিল, এটি +++++++; সি ++ 03 তে ভাল সংজ্ঞায়িত?
শিল্প-প্রতিরোধী

11

অন্যরা i += ++iযেমন বলেছে, আপনার উদাহরণটি ব্যবহারকারী-সংজ্ঞায়িত প্রকারের সাথে কাজ করে যেহেতু আপনি ফাংশনগুলি কল করছেন এবং ফাংশনগুলি সিকোয়েন্স পয়েন্ট নিয়ে গঠিত।

অন্যদিকে, a[++i] = iধরে নেওয়া এত ভাগ্যবান নয় যে aএটি আপনার প্রাথমিক অ্যারে টাইপ, বা এমনকি কোনও ব্যবহারকারী নির্ধারিত হয়েছে। আপনি এখানে যে সমস্যাটি পেয়েছেন তা হ'ল আমরা জানি না যে সংক্ষেপে প্রকাশের অংশটি iপ্রথমে মূল্যায়ন করা হয়। এটি হতে পারে যে সেখানে বস্তুটি পুনরুদ্ধার করার জন্য ++iমূল্যায়ন করা হয়েছে, operator[](অথবা কাঁচা সংস্করণে) iপাস করা হয়েছে , এবং তারপরে এর মানটি (যা আমার বর্ধিত হওয়ার পরে) হয়ে যায়। অন্যদিকে, সম্ভবত পরবর্তী দিকটি প্রথমে মূল্যায়ন করা হয়, পরবর্তী কার্যের জন্য সংরক্ষণ করা হয় এবং তারপরে ++iঅংশটি মূল্যায়ন করা হয়।


সুতরাং ... ফলাফলটি কি তবে ইউবির চেয়ে অনির্ধারিত, যেহেতু অভিব্যক্তিগুলির মূল্যায়নের আদেশটি অনির্ধারিত?
ফিলিপ পটার

@ ফিলিপ: অনির্ধারিত মানে হ'ল আমরা কম্পাইলারটি আচরণটি নির্দিষ্ট করার প্রত্যাশা করি, তবে অপরিজ্ঞাতভাবে এরকম কোনও বাধ্যবাধকতা নেই। আমি মনে করি এটি সংজ্ঞায়িতকারীদের অপ্টিমাইজেশনের জন্য আরও বেশি জায়গা দেওয়ার জন্য এটি এখানে অপরিজ্ঞাত।
ম্যাথিউ এম .9

@ নোয়া: আমিও একটি প্রতিক্রিয়া পোস্ট করেছি। দয়া করে এটি পরীক্ষা করে দেখুন এবং আমাকে আপনার চিন্তাভাবনা জানান। :-)
নওয়াজ

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

4
@ ফিলিপ: এটি কেবল অনির্ধারিত আচরণকে অনির্ধারিত আচরণ হিসাবে সংজ্ঞায়িত করে না। আবার, যদি অনির্দিষ্ট আচরণের পরিসীমাতে এমন কিছু অন্তর্ভুক্ত থাকে যা অপরিজ্ঞাত হয়, তবে সামগ্রিক আচরণটি অপরিজ্ঞাত। যদি অনির্দিষ্ট আচরণের ব্যাপ্তিটি সমস্ত সম্ভাবনায় সংজ্ঞায়িত করা হয়, তবে সামগ্রিক আচরণ অনির্দিষ্ট। তবে আপনি ঠিক দ্বিতীয় পয়েন্টে রয়েছেন, আমি একজন ব্যবহারকারী-সংজ্ঞায়িত aএবং বিল্টিনের কথা ভাবছিলাম i
স্টিভ জেসোপ

8

আমি মনে করি এটি সঠিকভাবে সংজ্ঞায়িত হয়েছে:

সি ++ খসড়া স্ট্যান্ডার্ড (n1905) থেকে 1.9 / 16:

"ফিরিয়ে দেওয়া মূল্যের অনুলিপি করার পরে এবং ফাংশনটির বাইরে কোনও অভিব্যক্তি কার্যকর করার আগে একটি ক্রম বিন্দু রয়েছে)। সি ++ এর কয়েকটি প্রসঙ্গ কোনও ফাংশন কলকে মূল্যায়নের কারণ করে, যদিও অনুবাদ ইউনিটে কোনও সম্পর্কিত ফাংশন কল সিনট্যাক্স উপস্থিত না হয়। [ উদাহরণস্বরূপ : একটি নতুন এক্সপ্রেশন মূল্যায়ন এক বা একাধিক বরাদ্দ এবং কনস্ট্রাক্টর ফাংশন আহ্বান করে; 5.3.4 দেখুন। অন্য উদাহরণের জন্য, রূপান্তর ফাংশন (12.3.2) এর অনুরোধ প্রসঙ্গগুলিতে উত্থিত হতে পারে যেখানে কোনও ফাংশন কল সিনট্যাক্স উপস্থিত হয় না end শেষ উদাহরণ ] ফাংশন-এন্ট্রি এবং ফাংশন-প্রস্থানের ক্রম পয়েন্টগুলি (উপরে বর্ণিত হিসাবে) ফাংশন কলের বৈশিষ্ট্যগুলি যেমন মূল্যায়িত হয় তেমনি এক্সপ্রেশনটির বাক্য বিন্যাস যাই হোক না কেনযে ফাংশন কল হতে পারে। "

আমি সাহসী যে অংশটি নোট করুন। এর অর্থ হ'ল ইনক্রিমেন্ট ফাংশন কল ( i.operator ++()) এর পরে কিন্তু কম্পাউন্ড অ্যাসাইনমেন্ট কল ( i.operator+=) এর আগে অবশ্যই একটি সিকোয়েন্স পয়েন্ট রয়েছে ।


6

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

a[++i] = i;

মামলা 1:

যদি aঅন্তর্নির্মিত ধরণের অ্যারে হয়। তাহলে নূহ যা বলেছেন তা সঠিক is এটাই,

a [++ i] = আমি ধরে নেওয়া এত ভাগ্যবান নয় যে এটি আপনার মূল অ্যারে টাইপ, অথবা এমনকি একটি ব্যবহারকারী একটি সংজ্ঞায়িত । আপনি এখানে যে সমস্যাটি পেয়েছেন তা হ'ল আমি জানি না যে আমি যুক্ত ভাবের কোন অংশটি প্রথমে মূল্যায়ন করা হয়।

সুতরাং a[++i]=iঅনির্ধারিত-আচরণের আহ্বান জানায় বা ফলাফল অনির্দিষ্ট। যাই হোক না কেন, এটি সঠিকভাবে সংজ্ঞায়িত হয়নি!

পিএস: উপরের উদ্ধৃতিতে, ধর্মঘট মাধ্যমে অবশ্যই আমার।

কেস 2:

যদি aব্যবহারকারী-সংজ্ঞায়িত প্রকারের কোনও বস্তু যা ওভারলোড করে operator[], তবে আবার দুটি ক্ষেত্রে রয়েছে।

  1. যদি ওভারলোডেড operator[]ফাংশনটির রিটার্ন টাইপ অন্তর্নির্মিত টাইপ হয়, তবে আবার a[++i]=iঅনির্ধারিত আচরণের অনুরোধ করুন বা ফলাফলটি অনির্ধারিত।
  2. কিন্তু যদি ওভারলোড এর রিটার্ন টাইপ operator[]ফাংশন ব্যবহারকারী-সংজ্ঞায়িত টাইপ করুন, তারপর এর আচরণ a[++i] = iএই ক্ষেত্রে যেহেতু ভালভাবে সংজ্ঞায়িত করা হয় (যতদূর আমি বুঝতে), a[++i]=iলেখা সমতূল্য a.operator[](++i).operator=(i);, যা হিসাবে একই a[++i].operator=(i);। অর্থাৎ নিয়োগ করা হয় operator=উপর প্রার্থনা পরার ফিরে বস্তুর a[++i], যা খুব ভাল-সংজ্ঞায়িত হতে সময় দ্বারা যেহেতু মনে হয় a[++i]আয়, ++iইতিমধ্যে মূল্যায়ন করা হয়েছে, এবং তারপর ফিরে বস্তুর কল operator=আপডেট মান ক্ষণস্থায়ী কাজ iআর্গুমেন্ট হিসাবে এটি। নোট করুন যে এই দুটি কলের মধ্যে একটি সিকোয়েন্স পয়েন্ট রয়েছে । এবং বাক্য গঠনটি নিশ্চিত করে যে এই দুটি কলের মধ্যে কোনও প্রতিযোগিতা নেই, এবংoperator[]প্রথমে প্রার্থনা করা হবে, এবং পরপরভাবে যুক্তিটি এতে ++iপ্রবেশ করায় প্রথমে মূল্যায়নও করা হত।

এটিকে ভাবুন someInstance.Fun(++k).Gun(10).Sun(k).Tun();যাতে প্রতিটি পরপর ফাংশন কল কিছু ব্যবহারকারীর দ্বারা সংজ্ঞায়িত প্রকারের কোনও বস্তু দেয়। আমার কাছে, এই পরিস্থিতিটি আরও এইরকম দেখাচ্ছে: eat(++k);drink(10);sleep(k)কারণ উভয় পরিস্থিতিতে প্রতিটি ফাংশন কলের পরে সিকোয়েন্স পয়েন্ট রয়েছে।

আমি ভুল হলে আমাকে সংশোধন করুন। :-)


4
@Nawaz k++এবং kকরছে না ক্রম পয়েন্ট দ্বারা পৃথক। এগুলি উভয়েরই মূল্যায়ন করা যেতে পারে Sunবা হয় মূল্যায়নের আগে Fun। ভাষার কেবলমাত্র এটির Funআগে মূল্যায়ন করা দরকার Sun, Funযুক্তিগুলির যুক্তির আগে মূল্যায়ন করা হয় না Sun। আমি আবার একই জিনিস আবার কোনও তথ্য উল্লেখ করতে সক্ষম না হয়ে আবার ব্যাখ্যা করছি, সুতরাং আমরা এখান থেকে অগ্রগতি করব না।
ফিলিপ পটার

4
@ নাওয়াজ: কারণ এমন কিছু নেই যা তাদেরকে পৃথক করার একটি সিকোয়েন্স পয়েন্ট নির্ধারণ করে। মৃত্যুর আগে এবং তার পরে সিকোয়েন্স পয়েন্ট রয়েছে Sunতবে Funএর যুক্তিটি ++kতার আগে বা পরে মূল্যায়ন করা যেতে পারে। মৃত্যুর আগে এবং তার পরে সিকোয়েন্স পয়েন্ট রয়েছে Funতবে Sunএর যুক্তিটি kতার আগে বা পরে মূল্যায়ন করা যেতে পারে। অতএব, একটি সম্ভাব্য কেস হ'ল উভয়ই kএবং উভয়ই ++kমূল্যায়ন করা হয় উভয়ের আগে Sunবা Funমূল্যায়ন করা হয়, এবং তাই উভয়ই ফাংশন-কল সিকোয়েন্স পয়েন্টগুলির আগে হয়, এবং তাই কোনও সিকোয়েন্স পয়েন্ট আলাদা হয় না kএবং ++k
ফিলিপ পটার

4
@ ফিলিপ: আমি আবার বলছি: এই পরিস্থিতি কীভাবে আলাদা eat(i++);drink(10);sleep(i);? ... এমনকি এখন, আপনি বলতে i++পারেন যে তার আগে বা পরে মূল্যায়ন করা যেতে পারে?
নওয়াজ

4
@ নাওয়াজ: আমি কীভাবে নিজেকে আরও স্পষ্ট করতে পারি? ফান / সান উদাহরণে, এবং এর মধ্যে কোনও ক্রম বিন্দু নেই । খাওয়া / পানীয় উদাহরণে, সেখানে হয় মধ্যে ক্রম পয়েন্ট হিসাবে এবং । k++kii++
ফিলিপ পটার

4
@ ফিলিপ: এটি মোটেই বোঝা যায় না। ফান () এবং সান () এর মধ্যে একটি সিকোয়েন্স পয়েন্ট বিদ্যমান তবে তাদের যুক্তির মধ্যে সিকোয়েন্স পয়েন্টের অস্তিত্ব নেই। এটি বলার মতো, সিকোয়েন্স পয়েন্ট (গুলি) এর মধ্যে eat()এবং sleep()বিদ্যমান, তবে সেখানে তর্কগুলির মধ্যে একটিও নেই। সিকোয়েন্স পয়েন্ট দ্বারা পৃথক দুটি ফাংশন কলগুলিতে কীভাবে যুক্তিগুলি একই সিকোয়েন্স পয়েন্টগুলির সাথে সম্পর্কিত হতে পারে?
নওয়াজ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.