C ++ نسخ بناء بناء و-تعيين السؤال
-
20-09-2019 - |
سؤال
وهنا مقتطف من البند 56 من كتاب "++ C Gotchas":
<اقتباس فقرة>وانها ليست من غير المألوف أن نرى بسيط تهيئة كائن Y مكتوبة أي من ثلاث طرق مختلفة، كما لو كانوا ما يعادلها.
اقتباس فقرة>Y a( 1066 );
Y b = Y(1066);
Y c = 1066;
<اقتباس فقرة>
في الواقع، كل ثلاثة من هذه ومن المحتمل أن يؤدي التهيئة في نفس رمز الكائن كائنا ولدت، لكنها ليست ما يعادلها. ومن المعروف أن التهيئة لكما توجيه التهيئة، وأنه لا بالضبط ما قد يتوقع المرء. ال ويتم إنجاز التهيئة من خلال والاحتجاج المباشر للY Y :: (الباحث).
ووالتهيئة للb و c أكثر تعقيدا. في الواقع، انهم جدا مركب. هذه هي كل نسخة التهيئة. في حالة تهيئة ب، ونحن يطلب إنشاء مؤقت مجهول من نوع Y، تهيئة مع قيمة 1066. ثم نستخدم هذا مؤقتة مجهول كمعلمة إلى النسخة منشئ لفئة Y تهيئة ب. وأخيرا، فإننا ندعو المدمر ل المجهول مؤقت.
اقتباس فقرة>لاختبار هذا، لقد فعلت ذلك لفئة بسيطة مع عضو البيانات (البرنامج المرفق في النهاية) وكانت النتائج مثيرة للدهشة. ويبدو أن للحالة ج، شيد الكائن منشئ نسخة بدلا من المقترح في الكتاب.
لا أحد يعرف إذا كان معيار اللغة قد تغيرت أم أن هذا مجرد ميزة تعظيم الاستفادة من مترجم؟ كنت باستخدام Visual Studio 2008.
ونموذج التعليمات البرمجية:
#include <iostream>
class Widget
{
std::string name;
public:
// Constructor
Widget(std::string n) { name=n; std::cout << "Constructing Widget " << this->name << std::endl; }
// Copy constructor
Widget (const Widget& rhs) { std::cout << "Copy constructing Widget from " << rhs.name << std::endl; }
// Assignment operator
Widget& operator=(const Widget& rhs) { std::cout << "Assigning Widget from " << rhs.name << " to " << this->name << std::endl; return *this; }
};
int main(void)
{
// construct
Widget a("a");
// copy construct
Widget b(a);
// construct and assign
Widget c("c");
c = a;
// copy construct!
Widget d = a;
// construct!
Widget e = "e";
// construct and assign
Widget f = Widget("f");
return 0;
}
وإخراج:
Constructing Widget a
Copy constructing Widget from a
Constructing Widget c
Assigning Widget from a to c
Copy constructing Widget from a
Constructing Widget e
Constructing Widget f
Copy constructing Widget from f
وكنت معظم فوجئت نتائج بناء d و e. على وجه الدقة، كنت أتوقع كائن فارغ المراد إنشاؤها، ثم كائن المراد إنشاؤها وتعيين إلى كائن فارغ. في الممارسة العملية، تم إنشاء الكائنات منشئ نسخة.
المحلول
وبناء الجملة
X a = b;
وحيث a و b من نوع X يعني دائما بناء نسخة. مهما كانت المتغيرات، مثل:
X a = X();
وتستخدم، ليس هناك مهمة مستمرة، ولم تكن أبدا. سيكون بناء وإسناد يكون شيئا مثل:
X a;
a = X();
نصائح أخرى
ويسمح المترجم إلى حالات الأمثل b
وc
أن تكون هي نفسها كما a
. وعلاوة على ذلك، بناء نسخة والمكالمات عامل التعيين يمكن القضاء عليها بالكامل من قبل مترجم على أي حال، لذلك كل ما تراه ليس بالضرورة الشيء نفسه مع المجمعين مختلفة أو إعدادات حتى مترجم.
واعتبارا من C ++ 17، كل ثلاثة من هذه <م> هي م> ما يعادلها (ما لم Y::Y(int)
هو explicit
، وهو ما من شأنه ببساطة عدم السماح c
) بسبب ما وغالبا ما تسمى <لأ href = "HTTP: // en.cppreference.com/w/cpp/language/copy_elision "يختلط =" noreferrer نوفولو "> إلزامية نسخة ترخيم .
وY c = 1066;
حتى يخلق فقط الكائن Y
واحد لأن نتيجة تحويل ضمني Y
هي prvalue التي يتم استخدامها لتهيئة c
بدلا من إنشاء مؤقتة.