سؤال

#include <iostream>
using namespace std;

class X {
        public:
                X() {
                        cout<<"Cons"<<endl;
                }
                X(const X& x){
                        cout<<"Copy"<<endl;
                }
                void operator=(const X& x){
                        cout<<"Assignment called";
                }
};

X& fun() {
        X s;
        return s;
}

int main(){
        X s = fun();
        return 0;
}

وهذا الرمز يدعو نسخة منشئ أيضا. لماذا هذا العمل؟ وأذكر أن أول مرة ركضت هذا البرنامج، فإنه SEG معيبا. ولكن بعد فترة من الوقت، والتي تدعو هذه النسخة سلبيات. ويعمل الآن !! غريب.

ولكن لو كنت محل، والمرح () كما يلي:

X fun() {
        X s;
        return s;
}

وثم نسخ سلبيات. لا يسمى. وأعتقد أن سلبيات نسخة. يمكن أن يسمى في هذه الحالة. ولكن كما أشار @ flyfishr64، RVO يأتي في اللعب هنا. لكنه لا يزال لا يفسر الحالة التي يكون فيها أنا عائد إشارة. أعتقد أنه يجب أن segfault دائما.

وأي تفسيرات؟

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

المحلول

لتوسيع على @ flyfishr64 في الجواب

ويتم استدعاء منشئ نسخة هنا لأن هذا:

X s = fun();

وهو التهيئة. كنت تستخدم المرح () لبناء الكائن، وليس استدعاء منشئ افتراضي. وهو ما يعادل:

X s(fun());

وو"سلبيات" تشاهد طباعتها هو مثيل في متعة (). انظر هذا المقال: عامل التعيين في C ++ للحصول على المزيد

نصائح أخرى

وهذا يعود إشارة إلى كائن على كومة التي لا وجود لها مرة واحدة إرجاع الأسلوب - المكدس unwinded، والذاكرة لا تزال هناك ولكن يجب أن لا يكون استخدامه

X& fun() {
        X s;
        return s;
}

وعند تغيير إلى ما يلي:

X fun() {
        X s;
        return s;
}

وأنت تعود الآن نسخة. إذا كان المترجم هو ذكي بما فيه الكفاية ربما القيام به:

X fun() {
    return X();
}

في هذه الحالة يتم توزيع X مباشرة في كومة المتصلين ذلك غير مطلوب هذه النسخة.

إذا كان segfault أو لا يعتمد على إذا كنت الوصول إلى الذاكرة غير صالحة.

في المثال الخاص بك لم يكن الوصول إلى أي القيم من الهيكل. لمعرفة segfault، أولا الحفاظ على المرجعية الذي عاد مع fun() إضافة بعض المتغيرات في بنية X وبعد العودة من fun() استدعاء طريقة أخرى أن يخصص داخليا بعض الذاكرة على كومة (وهذا ينبغي أن الكتابة الذاكرة الأصلية المستخدمة من قبل X في fun) ومخازن بعض القيم على كومة (الأفضل 0 ل). بعد هذه الطريقة الثانية في محاولة العودة إلى طباعة القيم من X باستخدام الإشارة الأصلية عاد من fun ...

في هذا الرمز:

X fun() {
        X s;
        return s;
}

لا يتم استدعاء منشئ نسخة الحصول على بسبب الأمثل قيمة إرجاع الذي يسمح للمترجم لتجاوز إنشاء المتغير المحلي الصورة "وبناء X مباشرة في متغير عاد.

ويمكنك قراءة المزيد حول RVO هنا

وعندما تعود إشارة إلى متغير محلي من هذا القبيل، كنت استدعاء السلوك undefinied.

ويحدث ذلك للعمل في هذه الحالة لأن أيا من وظائف class X فعلا استخدام مؤشر this، لذلك لا يهم أنه لم يعد صالحا.

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