سؤال

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

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

المحلول

لمتابعة ما قاله @[don.neufeld.myopenid.com]، فهي ليست مجرد نسخة سطحية، ولكنها إما (اختر ما يناسبك) تسرب للذاكرة أو مؤشر متدلي.

// memory leak (note that the pointer is never deleted)
class A
{
  B *_b;
  public:
  A()
  : _b(new B)
  {
  }
};

// dangling ptr (who deletes the instance?)
class A
{
  B *_b;
  public:
  A()
  ... (same as above)

  ~A()
  {
    delete _b;
  }
};

لحل هذه المشكلة، هناك عدة طرق.

قم دائمًا بتنفيذ مُنشئ النسخ وعامل التشغيل= في الفئات التي تستخدم مؤشرات الذاكرة الأولية.

class A
{
  B *_b;
  public:
  A()
  ... (same as above)

  ~A()
  ...

  A(const A &rhs)
  : _b(new B(rhs._b))
  {
  }

  A &operator=(const A &rhs)
  {
    B *b=new B(rhs._b);
    delete _b;
    _b=b;
    return *this;
};

وغني عن القول أن هذا يمثل ألمًا كبيرًا وهناك عدد لا بأس به من التفاصيل الدقيقة التي يجب تصحيحها.لست متأكدًا تمامًا من أنني فعلت ذلك هنا وقد فعلت ذلك عدة مرات.لا تنس أنه يتعين عليك نسخ جميع الأعضاء - إذا أضفت بعض الأعضاء الجدد لاحقًا، فلا تنس إضافتهم أيضًا!

اجعل منشئ النسخ والمشغل= خاصًا في صفك. هذا هو الحل "قفل الباب".إنها بسيطة وفعالة، ولكنها في بعض الأحيان مفرطة في الحماية.

class A : public boost::noncopyable
{
  ...
};

لا تستخدم أبدًا المؤشرات الأولية. هذا بسيط وفعال.هناك الكثير من الخيارات هنا:

  • استخدم فئات السلسلة بدلاً من مؤشرات الحرف الأولية
  • استخدم std::auto_ptr، وboost::shared_ptr، وboost::scoped_ptr وما إلى ذلك

مثال:

// uses shared_ptr - note that you don't need a copy constructor or op= - 
// shared_ptr uses reference counting so the _b instance is shared and only
// deleted when the last reference is gone - admire the simplicity!
// it is almost exactly the same as the "memory leak" version, but there is no leak
class A
{
  boost::shared_ptr<B> _b;
  public:
  A()
  : _b(new B)
  {
  }
};

نصائح أخرى

نعم، هذا هو نسخة الضحلة. لديك الآن نسختين من ليالي (واحد في المتصل، واحدة على كومة كمعلمة)، والتي تحتوي على كل مؤشر إلى أن نفس الكتلة من الذاكرة.

وسيكون لديك نسختين من البنية s، كل منها سوف يكون على مؤشر i الخاصة، ولكن كل من مؤشرات i له نفس القيمة لافتا إلى العنوان نفسه في الذاكرة - لذلك نعم، وسوف يكون نسخة ضحلة.

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