المدمر دعا الكائن عند إضافة إلى الأمراض المنقولة جنسيا::قائمة

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

  •  21-08-2019
  •  | 
  •  

سؤال

لدي فو كائن ، std::قائمة القابضة الحالات من ذلك.مشكلتي هي أنني عندما تضيف مثيل جديد إلى القائمة ، فإنه أول من يدعو المنشئ ولكن بعد ذلك أيضا dtor.ثم dtor على سبيل المثال (حسب هذا المؤشر).

مثيل واحد يضاف إلى قائمة ولكن منذ dtor (جنبا إلى جنب مع الآباء) ويسمى الكائن غير قادر على استخدامها كما هو متوقع.

هيريس بعض تبسيط التعليمات البرمجية لتوضيح المشكلة:

#include <iostream>
#include <list>

class Foo
{
public:
    Foo()
    { 
        int breakpoint = 0;
    }
    ~Foo()
    { 
        int breakpoint = 0;
    }
};

int main()
{
    std::list<Foo> li;
    li.push_back(Foo());
}
هل كانت مفيدة؟

المحلول

عند push_back() فو كائن كائن نسخ إلى قائمة الداخلية وهياكل البيانات ، ولذلك Dtor و المنشئ من حالة أخرى تسمى.

كل القياسية الخاصة بلبنان أنواع الحاويات في C++ تأخذ البنود الخاصة بهم من حيث القيمة ، ولذلك نسخ منها حسب الحاجة.على سبيل المثال كلما ناقلات يحتاج إلى النمو ، فمن الممكن أن كافة القيم في ناقلات الحصول على نسخ.

ربما كنت ترغب في تخزين مؤشرات بدلا من الأشياء في القائمة.من يفعل ذلك, فقط مؤشرات الحصول على نسخ بدلا من الكائن.ولكن قبل القيام بذلك ، يجب أن تأكد من حذف الكائنات ذات مرة كنت فعلت:

for (std::list<Foo*>::iterator it = list.begin(); it != list.end(); ++it) {
    delete *it;
}
list.clear();

بدلا من ذلك, يمكنك محاولة استخدام بعض نوع من 'مؤشر ذكية' الفئة ، على سبيل المثال من دفعة المكتبات.

نصائح أخرى

وإنك لعلى خلق فو مؤقت هنا:

li.push_back( Foo() )

وpush_back النسخ التي فو في هياكل البيانات الداخلية. يتم تدمير فو مؤقت بعد تنفيذ push_back، والتي سوف استدعاء المدمر.

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

.

استخدم هذا الكائن على فهم:

class Foo
{
public:
    Foo(int x): m_x(x)
    { 
    std::cout << "Constructed Object: " << m_x << ")\n";
    }
    Foo(Foo const& c): m_x(c.m_x+100)
    {
    std::cout << "Copied Object: " << m_x << ")\n";
    }
    ~Foo()
    {  
    std::cout << "Destroyed Object: " << m_x << ")\n";
    }
};

والرئيسي الأولى

std::list<Foo*> li;
li.push_back(Foo(1));

وهنا يمكننا إنشاء كائن فو مؤقت، وندعو push_back (). يحصل نسخ كائن مؤقت في قائمة وترجع الدالة. عند الانتهاء من هذا البيان ثم يتم تدمير كائن مؤقت (عبر المدمر). عندما يتم تدمير القائمة فإنه سيتم أيضا تدمير كل obejcts أنه يحتوي على (فو هو كائن مع المدمر ذلك يشمل تدمير استدعاء المدمر).

وهكذا سترى سومثينغ مثل هذا:

Constructed Object: 1
Constructed Object: 101
DestroyedObject: 1
DestroyedObject: 101

في المثال الثاني لديك:

std::list<Foo*> li;
li.push_back(new Foo(1));

وهنا حيوي إنشاء كائن على الكومة. ثم استدعاء push_back (). هنا يتم نسخ المؤشر إلى قائمة (مؤشر لا يوجد لديه منشئ / المدمر) حتى لا يحدث أي شيء آخر. يحتوي على قائمة الآن مؤشر إلى كائن على الكومة. عندما ترجع الدالة أي شيء آخر هو القيام به. عندما يتم تدمير القائمة أنه يدمر (لاحظ الفرق الدقيق سطاء تدمير وحذف) الكائن أنه يحتوي على (مؤشر) ولكن لا يوجد لديه مؤشر المدمر حتى لا يحدث أي شيء أي سوف تسرب الذاكرة.

وهكذا سترى سومثينغ مثل هذا:

Constructed Object: 1

ما يحدث في الواقع هنا هو أن تخزين نسخ من تمرير كائن في القائمة ، لأنك إرساله من القيمة بدلا من الإشارة.لذا فإن أول dtor الذي يسمى يسمى فعلا على وجوه يمكنك تمرير إلى push_back الطريقة ولكن مثيل جديد تم إنشاؤه من قبل ثم هو الآن المخزنة في القائمة.

إذا كنت لا تريد نسخة من فو كائن إلى إنشاء متجر مؤشرات فو الكائنات في القائمة بدلا من الكائنات نفسها.بالطبع عندما يفعل ذلك سيكون لديك بشكل صحيح تحرير الذاكرة على تدمير القائمة.

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

#include <iostream>
#include <list>

class Foo
{
public:
    Foo()
    { 
        int breakpoint = 0;
    }
    ~Foo()
    { 
        int breakpoint = 0;
    }
};

int main()
{
    std::list<Foo*> li;
    li.push_back(new Foo());
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top