سؤال

متعلق ب: كيفية تهيئة عضو غير POD في Union

يقول المعيار

قد يكون لدى عضو بيانات غير ثابت واحد على الأكثر في الاتحاد مُهيئ معزز أو مساوٍ.

لكن

struct Point {
    Point() {}
    Point(int x, int y): x_(x), y_(y) {}
    int x_, y_;
};

union U {
    int z;
    double w;
    Point p = Point(1,2);
};


#include <iostream>
int main () {
    U u;
    std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
}

مطبوعات 4196960:0 بدلا من المتوقع 1:2.

أنا أعتبر هذا خطأ مترجم.هل هذا صحيح؟

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

المحلول

ينص C++11 [class.ctor]/5 على ما يلي:

أ تقصير منشئ لفئة X هو منشئ الطبقة X التي يمكن استدعاؤها دون وسيطة.إذا لم يكن هناك منشئ معلن من قبل المستخدم للفئة X, ، يتم الإعلان ضمنيًا عن المُنشئ الذي لا يحتوي على معلمات على أنه متخلف (8.4).المنشئ الافتراضي المُعلن عنه ضمنيًا هو inline public عضوا في فئتها.منشئ افتراضي افتراضي للفئة X يتم تعريفه على أنه محذوف إذا:

  • X هي فئة شبيهة بالاتحاد تحتوي على عضو متغير مع مُنشئ افتراضي غير تافه،
  • أي عضو بيانات غير ثابت مع لا قوس أو يساوي البادئ هو من النوع المرجعي،
  • أي عضو بيانات غير ثابت غير متغير من النوع المؤهل const (أو صفيف منه) بدون قوس أو يساوي البادئ لا يحتوي على مُنشئ افتراضي يوفره المستخدم،
  • X هو اتحاد وجميع أعضائه المتغيرين هم من النوع المؤهل الثابت (أو مجموعة منها)،
  • X هي فئة غير نقابية وجميع أعضاء أي عضو اتحادي مجهول هم من النوع المؤهل الثابت (أو مجموعة منها)،
  • أي فئة أساسية مباشرة أو افتراضية، أو عضو بيانات غير ثابت بدون قوس أو يساوي البادئ, ، لديه نوع الفصل M (أو مجموعة منها) وإما M لا يحتوي على مُنشئ افتراضي أو دقة تحميل زائد (13.3) كما هو مطبق عليه Mيؤدي المُنشئ الافتراضي إلى غموض أو إلى وظيفة تم حذفها أو لا يمكن الوصول إليها من المُنشئ الافتراضي الافتراضي، أو
  • أي فئة أساسية مباشرة أو افتراضية أو عضو بيانات غير ثابت لديه نوع به أداة إتلاف تم حذفها أو لا يمكن الوصول إليها من المُنشئ الافتراضي الافتراضي.

يكون المُنشئ الافتراضي أمرًا تافهًا إذا لم يتم توفيره من قبل المستخدم وإذا:

  • لا تحتوي فئتها على وظائف افتراضية (10.3) ولا تحتوي على فئات أساسية افتراضية (10.1).
  • لا يوجد عضو بيانات غير ثابت في فئته لديه قوس أو يساوي البادئ, ، و
  • تحتوي جميع الفئات الأساسية المباشرة من فئتها على مُنشئات افتراضية تافهة، و
  • بالنسبة لجميع أعضاء البيانات غير الثابتة في فئتها والذين هم من نوع الفئة (أو مصفوفة منها)، فإن كل فئة لها مُنشئ افتراضي تافه.

خلاف ذلك، المنشئ الافتراضي هو غير تافهة.

منذ الهيكل Point في OP لديه مُنشئ افتراضي غير تافه،

Point() {}

مُنشئ افتراضي افتراضي لاتحاد يحتوي على عضو من النوع Point يجب يتم تعريفه على أنه محذوف وفقًا للرصاصة الأولى:

  • X هي فئة تشبه الاتحاد ولها عضو متغير مع مُنشئ افتراضي غير تافه

مما أدى إلى سوء صياغة البرنامج المقدم في OP.

ومع ذلك، يبدو أن اللجنة تعتبر هذا عيبًا في حالة أن أحد أعضاء النقابة لديه قوس أو يساوي البادئ, لكل قضية مجموعة العمل الأساسية 1623:

وفقًا للفقرة 12.1 [class.ctor] 5،

يتم تعريف المُنشئ الافتراضي الافتراضي للفئة X على أنه محذوف إذا:

  • X هي فئة شبيهة بالاتحاد تحتوي على عضو متغير مع مُنشئ افتراضي غير تافه،

  • ...

  • X هو اتحاد وجميع أعضائه المتغيرين هم من النوع المؤهل الثابت (أو مجموعة منها)،

  • X هي فئة غير نقابية وجميع أعضاء أي عضو اتحادي مجهول هم من النوع المؤهل الثابت (أو مجموعة منها)،

  • ...

لأن وجود مُهيئ عضو بيانات غير ثابت هو المعادل الأخلاقي لـ a تهيئة الذاكرة, ، ربما ينبغي تعديل هذه القواعد حتى لا يتم تعريف المنشئ الذي تم إنشاؤه على أنه محذوف عندما يكون لدى عضو الاتحاد مُهيئ عضو بيانات غير ثابت.(لاحظ المراجع غير المعيارية في 9.5 [class.union] الفقرات 2-3 و7.1.6.1 [dcl.type.cv] الفقرة 2 والتي قد تحتاج أيضًا إلى التحديث إذا تم تغيير هذا القيد.)

سيكون من المفيد أيضًا إضافة متطلب إلى 9.5 [class.union] يتطلب إما مُهيئ عضو بيانات غير ثابت أو مُنشئ يوفره المستخدم إذا كان جميع أعضاء الاتحاد لديهم أنواع مؤهلة بشكل ثابت.

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

العدد 1623 يحمل حالة "صياغة"، مما يشير إلى أن اللجنة تعتقد أن الموضوع ربما يكون عيبًا - وإلا فلماذا تسمح قوس أو يساوي البادئ لعضو النقابة؟- ولكن لم يخصص الوقت بعد لتحديد الصياغة المناسبة للقرار.في الواقع، الفقرة هي نفسها إلى حد كبير في مسودة C++ 14 الحالية N3936 ([class.ctor]/4)، باستثناء أن عبارة "أي فئة أساسية مباشرة أو افتراضية أو عضو بيانات غير ثابت" يتم استبدالها في كل مكان بـ أبسط "أي كائن فرعي يحتمل إنشاؤه."

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

ربما ينبغي على دول مجلس التعاون الخليجي إما أن تتوافق مع المعيار وتشخيص البرنامج على أنه غير صحيح، أو محاكاة سلوك clang وإنشاء مُنشئ مناسب من قوس أو يساوي البادئ.

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