لماذا استخدام = إلى التهيئة نوع بدائي في C++?

StackOverflow https://stackoverflow.com/questions/353632

  •  20-08-2019
  •  | 
  •  

سؤال

حيث أعمل معظم الناس يعتقدون أن الأشياء هي أفضل initialised باستخدام C++-أسلوب البناء (مع الأقواس) ، في حين بدائية يجب أن تكون أنواع initialised مع = المشغل:

std::string strFoo( "Foo" );
int nBar = 5;

لا أحد يبدو أن تكون قادرة على تفسير لماذا يفضلون الأمور على هذا النحو ، على الرغم من.أستطيع أن أرى ذلك std::string = "Foo"; لن يكون مجديا لأن ذلك ينطوي على نسخة إضافية ، ولكن ما هو الخطأ مع طرد = مشغل تماما باستخدام الأقواس في كل مكان ؟

هو مشترك الاتفاقية ؟ ما هي الفكرة من وراء ذلك ؟

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

المحلول

وإلا إذا كنت قد ثبت أنه يهم فيما يتعلق بالأداء، وأود أن لا تقلق حول نسخة إضافية باستخدام عامل التعيين في المثال الخاص بك (std::string foo = "Foo";). سأكون مندهشا جدا اذا كان هذا نسخة حتى وجود بمجرد إلقاء نظرة على رمز الأمثل، وأعتقد أن سيدعو فعلا منشئ معلمات المناسب.

في الإجابة على سؤالك، نعم، وانا اقول انه من اتفاقية شائعة جدا. تقليديا، وقد اعتاد الناس مهمة لتهيئة أنواع مدمج، وليس هناك سبب مقنع لتغيير هذا التقليد. قراءة والعادة هي أسباب وجيهة تماما لهذه الاتفاقية نظرا لمدى تأثير يذكر لها على رمز النهائي.

نصائح أخرى

تهيئة المتغيرات مع = المشغل أو مع دعوة منشئ هي لغويا نفسه ، إنه مجرد سؤال من نمط.أنا أفضل = مشغل لأنه يقرأ أكثر من الطبيعي.

باستخدام = المشغل عادة لا تولد نسخة إضافية - فقط المكالمات العادية منشئ.نلاحظ أن مع غير أنواع بدائية, هذا هو فقط من أجل التهيئة التي تحدث في نفس الوقت الإعلانات.قارن:

std::string strFooA("Foo");  // Calls std::string(const char*) constructor
std::string strFoo = "Foo";  // Calls std::string(const char*) constructor
                             // This is a valid (and standard) compiler optimization.

std::string strFoo;  // Calls std::string() default constructor
strFoo = "Foo";      // Calls std::string::operator = (const char*)

عندما يكون لديك غير تافهة الافتراضي الصانعين ، هذا الأخير يمكن أن يكون البناء أكثر قليلا فعالة.

على C++ القياسية, القسم 8.5 الفقرة 14 دولة:

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

جزء من القسم 12.2 الدول:

حتى عند إنشاء كائن مؤقت هو تجنب كل الدلالية القيود يجب أن تحترم كما لو كان كائن مؤقت تم إنشاؤه.[على سبيل المثال:حتى لو نسخ لم يتم استدعاء منشئ كل الدلالية القيود ، مثل الوصول (11), يجب أن يكون راضيا.]

شعرت بالحاجة إلى آخر سخيفة litb بعد.

string str1 = "foo";

ويسمى نسخ-التهيئة, لأن ما المترجم لا, إذا كان لا elide أي المؤقتات،:

string str1(string("foo")); 

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

T t = u; // u of type U

هو صالح.

في constrast,

string str1("foo");

يفعل بالضبط ما هو مكتوب ، ويسمى توجيه التهيئة.كما أنها تعمل مع صريح المنشئات.

بالمناسبة يمكنك تعطيل eliding من المؤقتات باستخدام -fno-elide-منشئات:

-fno-elide-constructors
    The C++ standard allows an implementation to omit creating a temporary which 
    is only used to initialize another object of the same type. Specifying this 
    option disables that optimization, and forces G++ to call the copy constructor 
    in all cases.

معيار يقول هناك عمليا لا فرق بين

T a = u;

و

T a(u);

إذا ر و نوع u هي أنواع بدائية.لذا يمكنك استخدام كل من الأشكال.أعتقد أنه مجرد أسلوب يجعل الناس استخدام النموذج الأول وليس الثاني.


بعض الناس قد استخدم لأول مرة في بعض الأوضاع ، لأنها ترغب في إزالة الغموض الإعلان:

T u(v(a));

migh ننظر إلى شخص تعريف متغير u تمت تهيئته باستخدام مؤقت من نوع v أن يحصل على المعلمة عن منشئ يسمى a.ولكن في الحقيقة ما المترجم هل هذا هو هذا:

T u(v a);

فإنه يخلق وظيفة الإعلان أن يأخذ الحجة من نوع v, و مع المعلمة يسمى a.حتى الناس

T u = v(a);

إلى إزالة الغموض ، على الرغم من أنها يمكن أن تفعل

T u((v(a)));

أيضا لأن هناك أبدا قوسين حول وظيفة معلمات المترجم أن تقرأ على أنها تعريف متغير بدلا من إعلان وظيفة أيضا :)

وأنت من المحتمل أن تجد هذا الرمز مثل

std::string strFoo = "Foo";

وسوف تجنب القيام نسخة إضافية ويجمع على نفس الرمز (مكالمة من منشئ-حجة واحدة) كما هو مع الأقواس.

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

وأعتقد أن استخدام = أو الأقواس لبناء المتغيرات المحلية إلى حد كبير مسألة اختيار شخصي.

حسنا، من يدري ما <م> أنها أعتقد، ولكنني أيضا يفضلون = لأنواع بدائية، وذلك أساسا لأنها ليست الأشياء، ولأن هذا هو الطريق "المعتادة" لتهيئة لهم.

وإنها قضية من النمط. حتى البيان أن "الأمراض المنقولة جنسيا :: سلسلة =" فو "؛ وتكون غير فعالة لأنها تنطوي على نسخة إضافية" غير صحيح. تتم إزالة هذا "نسخة إضافية" من قبل المجمع.

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

وحجة واحدة واحدة يمكن أن تجعل ل:

والأمراض المنقولة جنسيا :: سلسلة فو ( "بار")؛

هل هذا يبقي الأمور على حالها حتى لو كانت التغييرات العد الحجة، أي بمعنى:.

وفو الأمراض المنقولة جنسيا :: سلسلة ( "بار"، 5)؛

ولا يعمل مع علامة '='.

وشيء آخر هو أن للكثير من الأشياء ل'=' يشعر غير طبيعي، على سبيل المثال يقول لديك فئة صفيف حيث يعطي حجة طول:

وصفيف آر = 5؛

لا أشعر أنني بحالة جيدة، لأننا لا بناء صفيف بقيمة 5، ولكن مع طول 5:

وصفيف وصول (5)؛

ويشعر أكثر طبيعية، منذ كنت بناء كائن مع المعلمة معين، وليس فقط نسخ القيمة.

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

foo::foo()   
  ,anInt(0)   
  ,aFloat(0.0)   
{   
}   
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top