سؤال

إذا كان "الاختبار" فصلًا عاديًا، فهل هناك فرق بين:

Test* test = new Test;

و

Test* test = new Test();
هل كانت مفيدة؟

المحلول

لنكن متحذلقين، لأن هناك اختلافات يمكن أن تؤثر فعليًا على سلوك شفرتك.الكثير مما يلي مأخوذ من التعليقات المقدمة إلى مقال "الشيء القديم الجديد"..

في بعض الأحيان، تتم تهيئة الذاكرة التي يتم إرجاعها بواسطة المشغل الجديد، وفي بعض الأحيان لا يتم ذلك اعتمادًا على ما إذا كان النوع الذي تقوم بتجديده أم لا POD (بيانات قديمة عادية), أو إذا كانت فئة تحتوي على أعضاء POD وتستخدم مُنشئًا افتراضيًا تم إنشاؤه بواسطة برنامج التحويل البرمجي.

  • في C++ 1998 هناك نوعان من التهيئة:الصفر والافتراضي
  • في C++ 2003، تم إضافة نوع ثالث من التهيئة، وهو تهيئة القيمة.

يفترض:

struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m

في مترجم C++ 98، يجب أن يحدث ما يلي:

  • new A - قيمة غير محددة
  • new A() - تهيئة صفر

  • new B - البناء الافتراضي (B::m غير مهيأ)

  • new B() - البناء الافتراضي (B::m غير مهيأ)

  • new C - البناء الافتراضي (C::m تمت تهيئته بصفر)

  • new C() - البناء الافتراضي (C::m تمت تهيئته بصفر)

في المترجم المتوافق مع C++03، يجب أن تعمل الأمور على النحو التالي:

  • new A - قيمة غير محددة
  • new A() - تهيئة القيمة A، وهي تهيئة صفرية لأنها POD.

  • new B - التهيئة الافتراضية (يترك B::m غير مهيأ)

  • new B() - تهيئة القيمة B التي تقوم بتهيئة جميع الحقول صفرًا نظرًا لأن المرجع الافتراضي الخاص بها هو برنامج التحويل البرمجي الذي تم إنشاؤه بدلاً من المحدد من قبل المستخدم.

  • new C - التهيئة الافتراضية لـ C، والتي تستدعي المُنشئ الافتراضي.

  • new C() - تهيئة القيمة لـ C، والتي تستدعي المُنشئ الافتراضي.

لذلك في جميع إصدارات C++ هناك فرق بين new A و new A() لأن A هو POD.

وهناك اختلاف في السلوك بين C++ 98 وC++ 03 بالنسبة لهذه الحالة new B().

هذه إحدى الزوايا المتربة في لغة C++ والتي يمكن أن تدفعك إلى الجنون.عند إنشاء كائن، أحيانًا تريد/تحتاج إلى الأقواس، وأحيانًا لا يمكنك الحصول عليها مطلقًا، وأحيانًا لا يهم.

نصائح أخرى

وnew Thing(); غير صريحة الذي تريد منشئ دعا في حين new Thing; تؤخذ على أنها تعني كنت لا تمانع إذا لم يتم استدعاء المنشئ.

إذا استخدمت على البنية / فئة مع منشئ المعرفة، ليس هناك فرق. إذا دعت البنية تافهة / فئة (على سبيل المثال struct Thing { int i; };) ثم new Thing; مثل malloc(sizeof(Thing)); في حين new Thing(); مثل calloc(sizeof(Thing)); - فإنه يحصل على صفر تهيئة

.

وومسكتك يكمن في ما بينهما:

struct Thingy {
  ~Thingy(); // No-longer a trivial class
  virtual WaxOn();
  int i;
};

وسلوك new Thingy; مقابل new Thingy(); في هذه الحالة تغير بين C ++ 98 و C ++ 2003. انظر شرح مايكل بير لماذا وكيف.

لا، إنهم متشابهون.ولكن هناك فرق بين :

Test t;      // create a Test called t

و

Test t();   // declare a function called t which returns a Test

هذا بسبب القاعدة الأساسية لـ C++ (و C):إذا كان هناك شيء يمكن أن يكون إعلانًا، فهو إعلان.

يحرر: فيما يتعلق بمشكلات التهيئة المتعلقة ببيانات POD والبيانات غير POD، بينما أتفق مع كل ما قيل، أود فقط أن أشير إلى أن هذه المشكلات لا تنطبق إلا إذا كان الشيء الجديد أو الذي تم إنشاؤه بطريقة أخرى لا يحتوي على مستخدم- منشئ محدد.إذا كان هناك مثل هذا المنشئ فسيتم استخدامه.بالنسبة لـ 99.99% من الفئات المصممة بشكل معقول سيكون هناك مثل هذا المُنشئ، وبالتالي يمكن تجاهل المشكلات.

بشكل عام لدينا التهيئة الافتراضية في الحالة الأولى وتهيئة القيمة في الحالة الثانية.

على سبيل المثال:في حالة int (نوع POD):

  • int* test = new int - لدينا أي تهيئة وقيمة الاختبار يمكن أن تكون موجودة.

  • int* test = new int() - *الاختبار سيكون له قيمة 0.

السلوك التالي يعتمد على نوع الاختبار الخاص بك.لدينا حالات مختلفة:يحتوي الاختبار على مُنشئ افتراضي، وقد أنشأ الاختبار مُنشئًا افتراضيًا، ويحتوي الاختبار على عضو POD، وغير عضو POD...

وعلى افتراض أن الاختبار هي فئة مع منشئ محددة، وليس هناك فرق. شكل الأخير يجعل من أكثر وضوحا قليلا أن منشئ اختبار في قيد التشغيل، ولكن هذا عن ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top