বুলিয়ানদের জন্য কেন সি ++ এর && = বা || = নেই?


126

সেখানে একটি হল "খুব খারাপ জিনিস" যে ঘটতে পারে &&=এবং ||=জন্য অন্বিত চিনি হিসেবে ব্যবহার করা হয়েছে bool foo = foo && barএবং bool foo = foo || bar?


5
এই অন্যান্য প্রশ্নটি দেখুন: স্ট্যাকওভারফ্লো / প্রশ্নগুলি / ২২২45৪৪৫/২ এটি জাভা সম্পর্কে, তবে সি বংশের ভাগ করে নেওয়ার ক্ষেত্রে একই যুক্তি বেশিরভাগ ক্ষেত্রেই প্রযোজ্য।
জেমসডলিন

মূলত, কেবল সি ++ এর কাছে এটি খ / সি থাকে না তারা এটি রাখেনি - রুবির মতো ভাষায় এটি রয়েছে। বু ...
Kache

2
তবে রুবিতে, কোনও ধরণের জন্য x ||= yমোটামুটি সি ++ এর সমান নয় x = x ? x : y;? অন্য কথায়, "ইতিমধ্যে সেট না থাকলে y তে সেট করুন"। এটি সি বা সি ++ এর চেয়ে যথেষ্ট কার্যকর x ||= y, যা ( (bool)yইতিমধ্যে সেট না করা থাকলে অপারেটর ওভারলোডিং বাদ দিয়ে) "সেট এক্স করে " করবে। আমি এর জন্য অন্য অপারেটর যুক্ত করতে উদ্বিগ্ন নই, এটি কিছুটা দুর্বল বলে মনে হচ্ছে। শুধু লিখুন if (!x) x = (bool)y। তবে তারপরে, আমি boolঅতিরিক্ত অপারেটরগুলি দেখতে চাইলে যথেষ্ট পরিমাণে ভেরিয়েবল ব্যবহার করি না যা কেবলমাত্র এক ধরণের সাথেই কার্যকর।
স্টিভ জেসোপ

1
আমি নিশ্চিত যে সি ++ এর প্রাথমিক কারণ সি নেই &&=বা ||=কেবল যে সি তা নেই। আমি যুক্তিসঙ্গতভাবে নিশ্চিত যে সি এর কাছে না থাকার কারণটি হল কার্যকারিতা যথেষ্ট উপকারী বলে মনে করা হয়নি।
জোনাথন লেফলার 18

2
এছাড়াও, অতি-পেডেন্টিক হওয়ায় স্বরলিপিটি bool foo = foo || bar;অনির্ধারিত আচরণের দিকে পরিচালিত করবে কারণ fooমূল্যায়নের আগে আরম্ভ করা হয়নি foo || bar। অবশ্যই, এটি এর মতো কিছু হওয়ার ইচ্ছা bool foo = …initialization…; …; foo = foo || bar;এবং প্রশ্নটি তখন বৈধ হিসাবে দাঁড়িয়েছে।
জোনাথন লেফলার

উত্তর:


73

একজন boolশুধুমাত্র হতে পারে trueবা falseC ++। যেমন ব্যবহার করে &=এবং |=তুলনামূলকভাবে নিরাপদ (যদিও আমি বিশেষভাবে স্বরলিপিটি পছন্দ করি না)। সত্য, তারা লজিকাল অপারেশনগুলির চেয়ে বিট অপারেশন সম্পাদন করবে (এবং এভাবে তারা সংক্ষিপ্ত-সার্কিট করবে না) তবে এই বিট অপারেশনগুলি একটি সু-সংজ্ঞায়িত ম্যাপিং অনুসরণ করে, যা উভয় অপারেন্ডের টাইপ হিসাবেbool কার্যকরভাবে লজিক্যাল অপারেশনের সমতুল্য is । 1

অন্য লোকেরা এখানে যা বলেছে তার বিপরীতে, boolসি ++ এর মধ্যে কখনই আলাদা মান থাকতে হবে না 2। মানটিকে একটিতে নির্ধারিত boolকরার সময়, এটি trueমান অনুযায়ী রূপান্তরিত হবে ।

পয়েন্টার boolব্যবহার reinterpret_castকরে একটিতে অবৈধ মান পাওয়ার একমাত্র উপায় :

int i = 2;
bool b = *reinterpret_cast<bool*>(&i);
b |= true; // MAY yield 3 (but doesn’t on my PC!)

তবে যেহেতু এই কোডটির ফলাফল অনির্ধারিত আচরণের ফলেই হয়, তাই আমরা সি ++ কোড মেনে চলার ক্ষেত্রে এই সম্ভাব্য সমস্যাটিকে নিরাপদে উপেক্ষা করতে পারি।


1 স্বীকার করেছেন যে এঞ্জুর মন্তব্য চিত্রিত করে এটি একটি বরং বড় সাবধানবাণী:

bool b = true;
b &= 2; // yields `false`.

কারণটি হল b & 2পূর্ণসংখ্যার প্রচার সম্পাদন করে যে এক্সপ্রেশনটি তার সমান হয় static_cast<int>(b) & 2, যার ফলশ্রুতি হয় 0, যা পরে আবার রূপান্তরিত হয় bool। সুতরাং এটি সত্য যে কোনওটির অস্তিত্ব operator &&=প্রকারের সুরক্ষার উন্নতি করবে।


4
তবে && এবং || অপারেটররা যে কোনও কিছুতে কাজ করবে যা কেবল বুলকে নয়, বুলে রূপান্তরিত করে।
dan04

13
এমনকি তারাও একই কাজ করে না ool ||এবং &&শর্টকাট, যেমন দ্বিতীয় তর্কটি অপারেন্ড হয় না যদি প্রথম অপারেন্ড true(শ্রদ্ধার falseজন্য &&) হয়। |, &, |=এবং &=সবসময় উভয় operands নির্ণয় করা।
নিকি

4
এটি && = এবং || = সি ++ অপারেটর নয় কেন এই প্রশ্নের উত্তর দেয় না।
থ্যাং করুন

9
এটি টাইপের বাম দিকে ব্যবহার করা নিরাপদ নয় , কারণ ডান হাতের পক্ষে অন্য ধরণের হওয়া সম্পূর্ণভাবে সম্ভব (যেমন বা অন্য কোনও সি স্ট্ডলিব ফাংশন যা সত্য মানের জন্য ননজারোকে ফিরিয়ে দেয়)। যদি আমাদের কাছে অনুমানমূলক ধারণা থাকে তবে এটি সম্ভবত ডান হাতকে রূপান্তর করতে বাধ্য করবে , যা তা নয় which অন্য কথায়, ফলাফল । &=boolboolislower&&=bool&=bool b = true; b &= 2;b == false
অ্যাঞ্জিউ আর তাই

2
@ অ্যান্টোনিও কঠোর ভিড়। 😝
কনরাড রুডল্ফ

44

&&এবং &বিভিন্ন শব্দার্থক আছে: &&প্রথম অপারেন্ড হলে দ্বিতীয় অপারেন্ডকে মূল্যায়ন করবে না false। যেমন কিছু

flag = (ptr != NULL) && (ptr->member > 3);

নিরাপদ, কিন্তু

flag = (ptr != NULL) & (ptr->member > 3);

উভয় অপারেন্ড টাইপ হলেও, এটি নয় bool

একই &=এবং সত্য |=:

flag = CheckFileExists();
flag = flag && CheckFileReadable();
flag = flag && CheckFileContents();

এর চেয়ে আলাদা আচরণ করবে:

flag = CheckFileExists();
flag &= CheckFileReadable();
flag &= CheckFileContents();

35
আমার মতে && = থাকার আরও সমস্ত কারণ। = পি
কাচি

4
যদিও এটি আসলে কোনও উত্তর নয়।
ক্যাটসকুল

27

সংক্ষিপ্ত উত্তর

সকল অপারেটরদের +=, -=, *=, /=, &=, |=... গাণিতিক এবং একই প্রত্যাশা প্রদান:

x &= foo()  // We expect foo() be called whatever the value of x

যাইহোক, অপারেটরগুলি &&=এবং ||=যৌক্তিক হবে এবং এই অপারেটরগুলি ত্রুটি-প্রবণ হতে পারে কারণ অনেক বিকাশকারী foo()সর্বদা ডাকা হবে বলে আশা করবে x &&= foo()

bool x;
// ...
x &&= foo();           // Many developers might be confused
x = x && foo();        // Still confusing but correct
x = x ? foo() : x;     // Understandable
x = x ? foo() : false; // Understandable
if (x) x = foo();      // Obvious
  • শর্টকাট পাওয়ার জন্য আমাদের কি সত্যই সি / সি ++ আরও জটিল করা দরকার x = x && foo()?

  • আমরা কি সত্যিই আরও ক্রিপ্টিক স্টেটমেন্টটিকে অস্পষ্ট করতে চাই x = x && foo()?
    বা আমরা কি অর্থপূর্ণ কোডটি লিখতে চাই if (x) x = foo();?


দীর্ঘ উত্তর

উদাহরণস্বরূপ &&=

যদি &&=অপারেটর উপলব্ধ ছিল, তবে এই কোড:

bool ok = true; //becomes false when at least a function returns false
ok &&= f1();
ok &&= f2(); //we may expect f2() is called whatever the f1() returned value

সমান:

bool ok = true;
if (ok) ok = f1();
if (ok) ok = f2(); //f2() is called only when f1() returns true

এই প্রথম কোডটি ত্রুটি-প্রবণ কারণ অনেক বিকাশকারীরা মনে করবেন যে f2()সবসময় প্রত্যাশিত f1()মানটি বলা হয়। এটি এমন লেখার মতো bool ok = f1() && f2();যেখানে f2()কেবল যখন f1()ফিরে আসে তখন ডাকা হয় true

  • বিকাশকারী যদি আসলেই ফিরে আসে f2()তখন কল করতে চায় , সুতরাং উপরের দ্বিতীয় কোডটি ত্রুটি-প্রবণ কম।f1()true
  • অন্যথায় (বিকাশকারী f2()সর্বদা ডাকতে চায় ), &=যথেষ্ট:

উদাহরণস্বরূপ &=

bool ok = true;
ok &= f1();
ok &= f2(); //f2() always called whatever the f1() returned value

তদুপরি, সংকলকের পক্ষে এই নীচের কোডটির তুলনায় এই উপরের কোডটি অনুকূল করা সহজ:

bool ok = true;
if (!f1())  ok = false;
if (!f2())  ok = false;  //f2() always called

তুলনা &&এবং&

আমরা ভাবতে পারি যে অপারেটররা &&এবং মূল্যগুলিতে &প্রয়োগ করার সময় একই ফলাফল দেয় bool?

আসুন নিম্নলিখিত সি ++ কোড ব্যবহার করে চেক করুন:

#include <iostream>

void test (int testnumber, bool a, bool b)
{
   std::cout << testnumber <<") a="<< a <<" and b="<< b <<"\n"
                "a && b = "<< (a && b)  <<"\n"
                "a &  b = "<< (a &  b)  <<"\n"
                "======================"  "\n";
}

int main ()
{
    test (1, true,  true);
    test (2, true,  false);
    test (3, false, false);
    test (4, false, true);
}

আউটপুট:

1) a=1 and b=1
a && b = 1
a &  b = 1
======================
2) a=1 and b=0
a && b = 0
a &  b = 0
======================
3) a=0 and b=0
a && b = 0
a &  b = 0
======================
4) a=0 and b=1
a && b = 0
a &  b = 0
======================

উপসংহার

অতএব হ্যাঁ আমরা প্রতিস্থাপন করতে পারেন &&দ্বারা &জন্য boolমান ;-)
তাই ভাল ব্যবহার &=পরিবর্তে &&=
আমরা &&=বুলিয়ানদের জন্য অকেজো হিসাবে বিবেচনা করতে পারি ।

একই জন্য ||=

অপারেটরও এর চেয়ে |=কম ত্রুটি-প্রবণ||=

যদি কোনও বিকাশকারী f2()কেবল f1()তার falseপরিবর্তে ফিরে আসে তখন কল করা উচিত :

bool ok = false;
ok ||= f1();
ok ||= f2(); //f2() is called only when f1() returns false
ok ||= f3(); //f3() is called only when f1() or f2() return false
ok ||= f4(); //f4() is called only when ...

আমি নিম্নলিখিত আরও বোধগম্য বিকল্প পরামর্শ:

bool ok = false;
if (!ok) ok = f1();
if (!ok) ok = f2();
if (!ok) ok = f3();
if (!ok) ok = f4();
// no comment required here (code is enough understandable)

অথবা আপনি যদি সমস্ত এক লাইনের শৈলীতে পছন্দ করেন:

// this comment is required to explain to developers that 
// f2() is called only when f1() returns false, and so on...
bool ok = f1() || f2() || f3() || f4();

13
আমি যদি আসলে এই আচরণটি চাই? বাম হাতের অভিব্যক্তি ভুল হলে ডান হাতের এক্সপ্রেশনটি কার্যকর করা হয় না। ভেরিয়েবলগুলি দু'বার লিখলে বিরক্ত হয়success = success && DoImportantStuff()
নিক্লাস আর

1
আমার পরামর্শ লিখতে হয় if(success) success = DoImportantStuff()। যদি বিবৃতিটির success &&= DoImportantStuff()অনুমতি দেওয়া হয়, তবে অনেক বিকাশকারীরা ভাবেন DoImportantStuff()যে সর্বদা এর মান যাই হোক না কেন বলা হয় success। আশা করি এটির উত্তর আপনি কী আশ্চর্য করেছেন ... আমি আমার উত্তরের অনেকগুলি অংশও উন্নত করেছি। আমার উত্তরটি এখন আরও বোধগম্য হলে দয়া করে বলুন? (আপনার মন্তব্যের উদ্দেশ্য সম্পর্কে) চিয়ার্স, আপনাকে দেখাবে ;-)
অলিব্রে

9
"যদি বিবৃতিটির success &&= DoImportantStuff()অনুমতি দেওয়া হয়, তবে অনেক বিকাশকারী মনে করবেন DoImportantStuff()সাফল্যের মূল্য যাই হোক না কেন সর্বদা বলা হয়" " আপনি if (success && DoImportantStuff())যদিও এটি সম্পর্কে বলতে পারেন । যতক্ষণ না তারা যদি সিনট্যাক্সের পিছনে যুক্তিটি মনে রাখে তবে তাদের সাথে কোনও সমস্যা না হওয়া উচিত &&=
পাইকচ

2
আমি দেখতে পাচ্ছি না যে লোকেরা কীভাবে ধরে নিতে পারে যে f1()সর্বদা মূল্যায়ন করে ok &&= f(1) তবে তা সর্বদা মূল্যায়ন করে না বলে মনে হয় না ok = ok && f(1)। আমার কাছে ঠিক তেমন সম্ভাবনা মনে হচ্ছে।
einpoklum

1
আমি আসলে ভেরিয়েবল ভি 1 এবং এক্সপ্রেশন ই v1 += e22 এর সিনট্যাকটিক চিনির সমতুল্য হব বলে আশা করি v1 = v1 + e1। শর্টহ্যান্ড স্বরলিপি, এটাই সব।
einpoklum
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.