سؤال

في C++ يمكنك تهيئة متغير في جملة if مثل:

if (CThing* pThing = GetThing())
{
}

لماذا نعتبر هذه سيئة أو جيدة ؟ ما هي مزايا وعيوب ؟

شخصيا أنا أحب هذا النمط لأنه يحد من نطاق pThing متغير, لذلك لا يمكن أبدا أن تستخدم عن طريق الخطأ عندما تكون فارغة.ومع ذلك, أنا لا أحب ذلك لا يمكنك أن تفعل هذا:

if (CThing* pThing = GetThing() && pThing->IsReallySomeThing())
{
}

إذا كان هناك طريقة لجعل العمل أعلاه, الرجاء نشر.ولكن إذا كان هذا غير ممكن, أود أن أعرف لماذا.

السؤال: اقترضت من هنا موضوع مماثل لكن PHP.

هل كانت مفيدة؟

المحلول

الشيء المهم هو أن إعلان في C++ ليست تعبير.

bool a = (CThing* pThing = GetThing()); // not legit!!

لا يمكنك أن تفعل كل إعلان ومنطقية في جملة if, C++ لغة المواصفات على وجه التحديد يسمح إما تعبير أو إعلان.

if(A *a = new A)
{
    // this is legit and a is scoped here
}

كيف يمكننا أن نعرف ما إذا كان يعرف بين مصطلح واحد آخر في التعبير ؟

if((A *a = new A) && a->test())
{
    // was a really declared before a->test?
}

لدغة الرصاصة و استخدام داخلي أنا.نطاق القواعد مفيدة و المنطق الخاص بك هو صريح:

if (CThing* pThing = GetThing())
{
    if(pThing->IsReallySomeThing())
    {
    }
}

نصائح أخرى

حول مزايا:

ينصح دائما لتحديد المتغيرات عند أول حاجة إليها ، وليس خط قبل.هذا هو تحسن القراءة من التعليمات البرمجية الخاصة بك, حيث يمكن للمرء أن يقول ما CThing هو دون التمرير و البحث حيث تم تعريف.

أيضا الحد من نطاق إلى حلقة/إذا كتلة أسباب المتغير unreferenced بعد تنفيذ كتلة التعليمات البرمجية ، مما يجعله مرشح لجمع القمامة (إذا كانت اللغة يدعم هذه الميزة).

if (CThing* pThing = GetThing())

فمن أسلوب سيئة, لأنه داخل if أنت لا تقدم تعبير منطقي.تقديم CThing*.

CThing* pThing = GetThing();
if (pThing != NULL)

هذا هو اسلوب جيد.

سبب واحد أنا عادة لا تفعل ذلك لأن من الأخطاء الشائعة من غاب '=' في اختبار شرطي.يمكنني استخدام الوبر مع الخطأ/تحذيرات مجموعة للقبض على أولئك.فإنه سيتم ثم يصيح عن جميع المهام داخل الشرطية.

فقط لمعلوماتك بعض كبار السن من Microsoft C++ compliers(البصرية استوديوهات 6،.NET 2003 على ما أظن) لا تتبع تماما النطاق القاعدة في بعض الحالات.

for(int i = 0; i > 20; i++) {
     // some code
}

cout << i << endl;

أنا يجب أن يكون خارج نطاق, ولكن هذا كان/هو رمز صالح.أنا أعتقد أنه كان يلعب خارج كسمة ، ولكن في رأيي انها مجرد عدم الامتثال.عدم الالتزام بمعايير سيئة.كما المطور على شبكة الإنترنت عن IE و Firefox.

يمكن لشخص مقابل تحقق لمعرفة ما إذا كان هذا لا يزال ساري المفعول ؟

هذا يجب أنلا يعمل في C++ منذعلى الرغم من أنها تدعم الدائرة القصيرة التقييم. ربمالا تحاول التالية:

if ((CThing* pThing = GetThing()) && (pThing->IsReallySomeThing()))
{
}

يخطئ..انظر ويسلي Tarle الجواب

يمكنك أيضا أن ترفق المهمة في مجموعة إضافية من ( ) لمنع رسالة تحذير.

أرى أنه نوع من الخطورة.رمز أدناه هو أكثر أمانا و أرفق الأقواس سوف لا تزال تحد من نطاق pThing في بالطريقة التي تريدها.

أفترض GetThing() أحيانا إرجاع NULL وهذا هو السبب أنا وضعت هذا مضحك الشرط في إذا() البيان.يمنع IsReallySomething() يطلق على مؤشر فارغة.

{
    CThing *pThing = GetThing();
    if(pThing ? pThing->IsReallySomeThing() : false)
    {
    // Do whatever
    }
}

أيضا لاحظ أنه إذا كنت تكتب رمز C++ كنت تريد أن تجعل المترجم تحذير عن "=" في عبارة شرطية (التي ليست جزءا من الإعلان) خطأ.

انها مقبولة و جيدة الترميز الممارسة.ولكن الناس الذين لا يأتون من انخفاض مستوى الترميز الخلفية ربما نختلف.

أشياء كثيرة.أولا وقبل كل شيء ، العارية المؤشرات.يرجى تجنبها بكل الوسائل.استخدام المراجع اختياري ، unique_ptr, shared_ptr.كملاذ أخير ، والكتابة الخاصة بك الطبقة التي تتعامل مع مؤشر ملكية أي شيء آخر.

استخدام موحدة التهيئة إذا كنت يمكن أن تتطلب C++11 (C++14 يفضل تجنب C++11 العيوب):- يتجنب = مقابل == الارتباك و هو أكثر صرامة في التحقق من الحجج إذا كان هناك أي.

if (CThing thing {})
{
}

تأكد من تنفيذ operator bool للحصول على التنبؤ التحويل من CThing إلى bool.لكن, نضع في اعتبارنا أن الناس قراءة رمز لن ترى operator bool الحق بعيدا.صراحة طريقة المكالمات عادة ما تكون أكثر قابلية للقراءة و الاطمئنان.إذا كنت يمكن أن تتطلب C++17, استخدام مهيئ الجملة.

if (CThing thing {}; thing.is_good())
{
}

إذا كان C++17 ليس خيارا ، استخدام الإعلان أعلاه إذا كما اقترح آخرون.

{
  CThing thing {};
  if (thing.is_good())
  {
  }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top