উপ-এক্সপ্রেশনগুলির মূল্যায়নের অনির্দিষ্ট আদেশের কারণে কোডটি অনির্দিষ্ট আচরণের প্রদর্শন করে যদিও এটি অনির্ধারিত আচরণকে সমর্থন করে না কারণ সমস্ত পার্শ্ব প্রতিক্রিয়াগুলি ফাংশনগুলির মধ্যে করা হয় যা এই ক্ষেত্রে পার্শ্ব প্রতিক্রিয়াগুলির মধ্যে একটি ক্রম সম্পর্কের পরিচয় দেয়।
প্রস্তাবটি এন 4228 এ এই উদাহরণটি উল্লেখ করা হয়েছে : আইডিয়োমেটিক সি ++ এর জন্য এক্সপ্রেশন মূল্যায়ন আদেশ সংশোধন করে যা প্রশ্নের কোড সম্পর্কে নিম্নলিখিতটি বলে:
[...] এই কোড সি ++ বিশেষজ্ঞদের দ্বারা পর্যালোচনা করা হয়েছে পৃথিবীব্যাপী এবং প্রকাশিত (C ++ Programming Language, 4 ম সংস্করণ।) তা সত্ত্বেও, মূল্যায়ন অনির্দিষ্ট অর্ডার তার দুর্বলতার শুধুমাত্র সম্প্রতি একটি টুল দ্বারা [আবিষ্কৃত হয়েছে .. ।]
বিশদ
এটি অনেকের কাছেই স্পষ্ট হতে পারে যে ফাংশনগুলির পক্ষে যুক্তিগুলির মূল্যায়নের একটি অনির্ধারিত ক্রম থাকে তবে এটি সম্ভবত এতটা স্পষ্ট নয় যে এই আচরণটি শিকলযুক্ত ফাংশন কলগুলির সাথে কীভাবে যোগাযোগ করে। আমি প্রথম যখন এই কেসটি বিশ্লেষণ করেছি এবং সমস্ত বিশেষজ্ঞ পর্যালোচকদের কাছে দৃশ্যত না তখন এটি আমার কাছে স্পষ্ট ছিল না ।
প্রথম নজরে এটি প্রদর্শিত হতে পারে যেহেতু প্রত্যেককে replace
বাম থেকে ডানে মূল্যায়ন করতে হয় যে সংশ্লিষ্ট ফাংশন আর্গুমেন্ট গ্রুপগুলি বাম থেকে ডানেও গ্রুপ হিসাবে মূল্যায়ন করতে হবে।
এটি ভুল, ফাংশন আর্গুমেন্টগুলির মূল্যায়নের একটি অনির্দিষ্ট অর্ডার রয়েছে যদিও চেইন ফাংশন কলগুলি প্রতিটি ফাংশন কলের জন্য একটি বাম থেকে ডানদিকে মূল্যায়ন আদেশ প্রবর্তন করে তবে প্রতিটি ফাংশন কলের আর্গুমেন্টগুলি কেবল সদস্য ফাংশন কলের সাথে সম্মতি রেখে সেগুলি কেবল ক্রমযুক্ত হয় যা তারা অংশ হয় এর বিশেষত এটি নিম্নলিখিত কলগুলিকে প্রভাবিত করে:
s.find( "even" )
এবং:
s.find( " don't" )
যেগুলি অনির্দিষ্টকালের জন্য শ্রদ্ধার সাথে ক্রমযুক্ত:
s.replace(0, 4, "" )
দুটি find
কল এর আগে বা পরে মূল্যায়ন করা যেতে পারে replace
, যেহেতু এটির প্রভাব যেহেতু s
এমনভাবে প্রভাবিত করে যা ফলাফলকে পরিবর্তন করতে পারে find
, এটি দৈর্ঘ্যের পরিবর্তন করে s
। সুতরাং যখন replace
দুটি find
কলের তুলনায় এটি মূল্যায়ন করা হয় তার উপর নির্ভর করে ফলাফলটি পৃথক হবে।
যদি আমরা শৃঙ্খলা প্রকাশের দিকে তাকাই এবং কিছু উপ-এক্সপ্রেশনগুলির মূল্যায়ন আদেশ পরীক্ষা করি:
s.replace(0, 4, "" ).replace( s.find( "even" ), 4, "only" )
^ ^ ^ ^ ^ ^ ^ ^ ^
A B | | | C | | |
1 2 3 4 5 6
এবং:
.replace( s.find( " don't" ), 6, "" );
^ ^ ^ ^
D | | |
7 8 9
নোট, আমরা সত্য যে উপেক্ষা করা হয় 4
এবং 7
আরও উপ-এক্সপ্রেশন বিভক্ত করা যেতে পারে। সুতরাং:
A
সিক্যুয়েন্সড B
যা আগে C
সিকোয়েন্সড হয় তার আগে সিক্যুয়েন্সড হয়D
1
থেকে 9
অনিশ্চিতভাবে নীচে তালিকাভুক্ত ব্যতিক্রম কিছু সঙ্গে অন্যান্য উপ-এক্সপ্রেশন থেকে সম্মান সঙ্গে সিকোয়েন্স হয়
1
থেকে 3
সামনে সিকোয়েন্স হয়B
4
থেকে 6
সামনে সিকোয়েন্স হয়C
7
থেকে 9
সামনে সিকোয়েন্স হয়D
এই ইস্যুটির মূল কথাটি হ'ল:
4
থেকে 9
অনিশ্চিতভাবে থেকে সম্মান সঙ্গে সিকোয়েন্স হয়B
মূল্যায়নের পছন্দগুলির পক্ষে 4
এবং 7
সম্মানের সাথে মূল্যায়নের সম্ভাব্য ক্রম যখন মূল্যায়নের B
মধ্যে clang
এবং gcc
কখন ফলাফলগুলির মধ্যে পার্থক্যটি ব্যাখ্যা করে f2()
। আমার পরীক্ষা clang
মূল্যায়ন B
মূল্যায়নের আগে 4
ও 7
যখন gcc
এটা মূল্যায়ন করেন। আমরা প্রতিটি ক্ষেত্রে কী ঘটছে তা প্রদর্শনের জন্য নিম্নলিখিত পরীক্ষার প্রোগ্রামটি ব্যবহার করতে পারি:
#include <iostream>
#include <string>
std::string::size_type my_find( std::string s, const char *cs )
{
std::string::size_type pos = s.find( cs ) ;
std::cout << "position " << cs << " found in complete expression: "
<< pos << std::endl ;
return pos ;
}
int main()
{
std::string s = "but I have heard it works even if you don't believe in it" ;
std::string copy_s = s ;
std::cout << "position of even before s.replace(0, 4, \"\" ): "
<< s.find( "even" ) << std::endl ;
std::cout << "position of don't before s.replace(0, 4, \"\" ): "
<< s.find( " don't" ) << std::endl << std::endl;
copy_s.replace(0, 4, "" ) ;
std::cout << "position of even after s.replace(0, 4, \"\" ): "
<< copy_s.find( "even" ) << std::endl ;
std::cout << "position of don't after s.replace(0, 4, \"\" ): "
<< copy_s.find( " don't" ) << std::endl << std::endl;
s.replace(0, 4, "" ).replace( my_find( s, "even" ) , 4, "only" )
.replace( my_find( s, " don't" ), 6, "" );
std::cout << "Result: " << s << std::endl ;
}
ফলাফল gcc
( এটি সরাসরি দেখুন )
position of even before s.replace(0, 4, "" ): 26
position of don't before s.replace(0, 4, "" ): 37
position of even after s.replace(0, 4, "" ): 22
position of don't after s.replace(0, 4, "" ): 33
position don't found in complete expression: 37
position even found in complete expression: 26
Result: I have heard it works evenonlyyou donieve in it
এর ফলাফল clang
( এটি সরাসরি দেখুন ):
position of even before s.replace(0, 4, "" ): 26
position of don't before s.replace(0, 4, "" ): 37
position of even after s.replace(0, 4, "" ): 22
position of don't after s.replace(0, 4, "" ): 33
position even found in complete expression: 22
position don't found in complete expression: 33
Result: I have heard it works only if you believe in it
এর ফলাফল Visual Studio
( এটি সরাসরি দেখুন ):
position of even before s.replace(0, 4, "" ): 26
position of don't before s.replace(0, 4, "" ): 37
position of even after s.replace(0, 4, "" ): 22
position of don't after s.replace(0, 4, "" ): 33
position don't found in complete expression: 37
position even found in complete expression: 26
Result: I have heard it works evenonlyyou donieve in it
স্ট্যান্ডার্ড থেকে বিশদ
আমরা জানি যে সাব-এক্সপ্রেশনগুলির মূল্যায়নগুলি অসতর্কিত না করা পর্যন্ত এটি সি ++ 11 স্ট্যান্ডার্ড বিভাগ 1.9
প্রোগ্রাম এক্সিকিউশন খসড়া থেকে এসেছে যা বলে:
উল্লিখিত ব্যতীত পৃথক অপারেটরগুলির অপারেটের এবং পৃথক অভিব্যক্তির subexpresstions এর মূল্যায়ন অনির্দিষ্ট। [...]
এবং আমরা জানি যে ফাংশন কল ফাংশনটির সাথে সম্পর্কের আগে পোস্টফিক্স এক্সপ্রেশন এবং ফাংশন বডি সম্পর্কে শ্রদ্ধার সাথে যুক্তিগুলি, বিভাগ থেকে 1.9
:
[...] কোনও ফাংশন কল করার সময় (ফাংশনটি ইনলাইন হোক বা না হোক), কোনও আর্গুমেন্ট এক্সপ্রেশনের সাথে সম্পর্কিত প্রতিটি মান গণনা এবং পার্শ্ব প্রতিক্রিয়া, বা ডাক ফাংশনকে চিহ্নিতকরণের পোস্টফিক্স এক্সপ্রেশন সহ প্রতিটি অভিব্যক্তি বা বিবৃতি কার্যকর করার আগে ক্রমযুক্ত হয় বলা ফাংশন এর শরীরে। [...]
আমরা আরও জানি যে শ্রেণীর সদস্য অ্যাক্সেস এবং সেইজন্য শৃঙ্খলা বাম থেকে ডানে বাম দিক থেকে মূল্যায়ন করবে, বিভাগের 5.2.5
সদস্য অ্যাক্সেস যা বলেছেন:
[...] বিন্দু বা তীর মূল্যায়ন করার আগে পোস্টফিক্স এক্সপ্রেশন; That৪
এই মূল্যায়নের ফলাফল এবং আইডি-এক্সপ্রেশন সহ পুরো পোস্টফিক্স এক্সপ্রেশনটির ফলাফল নির্ধারণ করে।
নোট, কেস যেখানে আইডি প্রকাশ আপ একটি অ-স্ট্যাটিক সদস্য ফাংশন হচ্ছে প্রান্ত এটা মূল্যায়ন ক্রম নির্দিষ্ট করে না অভিব্যক্তি-তালিকা মধ্যে ()
যেহেতু একটি পৃথক উপ-অভিব্যক্তি। 5.2
পোস্টফিক্স এক্সপ্রেশন থেকে প্রাসঙ্গিক ব্যাকরণ :
postfix-expression:
postfix-expression ( expression-listopt)
postfix-expression . templateopt id-expression
সি ++ 17 পরিবর্তন
প্রস্তাব p0145r3: আইডিয়োমেটিক সি ++ এর জন্য এক্সপ্রেশন মূল্যায়ন আদেশকে সংশোধন করে বেশ কয়েকটি পরিবর্তন আনা হয়েছে। পোস্টফিক্স-এক্সপ্রেশন এবং তাদের এক্সপ্রেশন-তালিকার জন্য মূল্যায়নের নিয়মের ক্রমকে শক্তিশালী করে কোডটিকে সুনির্দিষ্ট আচরণের ব্যবস্থা করে এমন পরিবর্তনগুলি সহ ।
[expr.call] পি 5 বলেছেন:
পোস্টফিক্স-এক্সপ্রেশনটি এক্সপ্রেশন-তালিকার প্রতিটি অভিব্যক্তির আগে এবং কোনও ডিফল্ট আর্গুমেন্টের অনুক্রম হয় । প্রতিটি সম্পর্কিত মান গণনা এবং পার্শ্ব প্রতিক্রিয়া সহ একটি প্যারামিটারের সূচনাটি অনির্দিষ্টকালের জন্য অন্য যে কোনও প্যারামিটারের সাথে সম্মতিযুক্ত sequ [দ্রষ্টব্য: যুক্তি মূল্যায়নের সমস্ত পার্শ্ব প্রতিক্রিয়াগুলি ক্রিয়াকলাপটি প্রবেশের আগেই সিকোয়েন্সড হয় (দেখুন 4.6)) Note সংক্ষেপে নোট] [উদাহরণ:
void f() {
std::string s = "but I have heard it works even if you don’t believe in it";
s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don’t"), 6, "");
assert(s == "I have heard it works only if you believe in it");
}
পরবর্তী উদাহরণ]
s.replace( s.replace( s.replace(0, 4, "" ).find( "even" ), 4, "only" ).find( " don't" ), 6, "" );