مدمر (برمجة حاسوب)

في البرمجة الموجهة للكائنات ، المدمر (يُختصر أحيانًا بـ dtor  ) هو طريقة يتم استدعاؤها ميكانيكيًا قبل تحرير ذاكرة الكائن .  يمكن أن يحدث ذلك عندما تكون مدة حياتها مرتبطة بالنطاق ويترك التنفيذ النطاق، أو عندما يتم تضمينها في كائن آخر تنتهي مدة حياته، أو عندما يتم تخصيصها بشكل ديناميكي ويتم إصدارها صراحةً. غرضه الرئيسي هو تحرير الموارد (تخصيصات الذاكرة، الملفات المفتوحة أو المقابس، اتصالات قاعدة البيانات ، أقفال الموارد ، وما إلى ذلك) التي تم الحصول عليها بواسطة الكائن أثناء حياته و/أو إلغاء تسجيلها من كيانات أخرى قد تحتفظ بالمراجع إليها. يُعد استخدام المدمرات ضروريًا لعملية تهيئة اكتساب الموارد (RAII).

في معظم أنواع خوارزميات جمع القمامة التلقائية ، قد يحدث تحرير الذاكرة بعد فترة طويلة من أن يصبح الكائن غير قابل للوصول، مما يجعل المدمرات (والتي تسمى المُنهيات في هذه الحالة) غير مناسبة لمعظم الاستعمالات. في مثل هذه اللغات، يتم تحرير الموارد إما من خلال بناء معجمي (مثل try..finally، أو "with" في Python أو "try-with-resources" في Java)، وهو ما يعادل RAII، أو صراحةً عن طريق استدعاء دالة (مكافئة للحذف الصريح)؛ على وجه الخصوص، تستخدم العديد من لغات البرمجة كائنية التوجه نمط التخلص .

 بناء جملة المدمر 

 سي++ : المدمرات لها نفس اسم الفئة التي ترتبط بها، ولكن مع بادئة (~). 
 دي : يتم إعلان المدمرات باستخدام الاسم ~this() (بينما يتم إعلان المنشئات باستخدام this() ).
 أوبجكت باسكال : المدمرات لها الكلمة الأساسية destructor ويمكن أن يكون لها أسماء محددة من قبل المستخدم، ولكن في الغالب يتم تسميتها Destroy .
 سي-الكائنية : طريقة التدمير لها اسم dealloc .
 بيرل : طريقة التدمير لها اسم DESTROY ؛ في امتداد نظام كائن Moose ، تسمى DEMOLISH .
 بي إتش بي : في بي إتش بي 5+، طريقة التدمير لها اسم __destruct . لم تكن هناك مدمرات في الإصدارات السابقة من بي إتش بي. Constructors and Destructors, from PHP online documentation 
 بايثون : هناك طرق __del__ تسمى المدمرات في دليل لغة بايثون 2،  ولكنها في الواقع عبارة عن أدوات نهائية كما هو معترف به في بايثون 3. 
 رست : طريقة التدمير للصدأ لها اسم drop . 
 سويفت : طريقة التدمير لها اسم deinit .

 في سي++ 
يحمل المدمر نفس اسم الفئة (class)، ولكن مع وجود علامة (~) قبله. Sebesta, Robert W. (2012). ""11.4.2.3 Constructors and Destructors"". Concepts of Programming Languages (print) (10th ed.). Boston, MA, USA: Addison-Wesley. p. 487. ISBN 978-0-13-139531-2. على سبيل المثال، ستحتوي الفئة المسماة foo على المدمر ~foo() . بالإضافة إلى ذلك، لا تحتوي المدمرات على معلمات أو أنواع إرجاع.  كما ذكر أعلاه، يتم استدعاء مدمر الكائن عندما تنتهي مدة حياة الكائن.  إذا تم إنشاء الكائن كمتغير تلقائي ، تنتهي مدة حياته ويتم استدعاء المدمر تلقائيًا عندما يخرج الكائن عن النطاق. نظرًا لأن لغة سي++ لا تحتوي على أداة جمع القمامة، فإذا تم إنشاء الكائن باستخدام عبارة new (بشكل ديناميكي على الكومة)، فسيتم استدعاء المدمر الخاص به عند تطبيق عامل delete على مؤشر إلى الكائن. عادةً ما تحدث هذه العملية داخل مدمر آخر، عادةً ما يكون مدمر كائن مؤشر ذكي .

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

لا ينبغي للمدمر أن يلقي استثناءً أبدًا. GotW #47: Uncaught exceptions Accessed 31 July 2011. 

تحتوي الأنواع القياسية التي لا تنتمي للمخططات على ما يسمى يمكن الوصول إليه باستخدام typedef أو وسيطات القالب. يتيح هذا البناء كتابة التعليمات البرمجية دون الحاجة إلى معرفة ما إذا كان المدمر موجودًا لنوع معين.int f() {
  int a = 123;
  using T = int;
  a.~T();
  return a; // undefined behavior
}في الإصدارات الأقدم من المعيار، تم تحديد  (المدمرات الزائفة) بحيث لا يكون لها أي تأثير، ومع ذلك تم تغيير ذلك في تقرير العيوب لجعلها تنهي عمر الكائن الذي يتم استدعاؤها عليه. 

 مثال 
#include <cstring>
#include <iostream>

class Foo {
public:
    Foo(): data_(new char[sizeof("Hello, World!")]) {
        std::strcpy(data_, "Hello, World!");
    }

    Foo(const Foo& other) = delete;             // disable copy construction
    Foo& operator=(const Foo& other) = delete;  // disable assignment

    ~Foo(void) { delete[] data_; }

private:
    friend std::ostream& operator<<(std::ostream& os, const Foo& foo) {
        os << foo.data_;
        return os;
    }

    char* data_;
};

int main() {
    Foo foo;
    std::cout << foo << std::endl;
}يجب تعطيل الكائنات التي لا يمكن نسخها و/أو تخصيصها بأمان من هذه الدلالات عن طريق إعلان دالات مقابلة على أنها محذوفة ضمن مستوى التغليف العام. يمكن العثور على وصف مفصل لهذه الطريقة في كتاب Scott Meyers الشهير، Effective Modern C++ (البند 11: "تفضيل الوظائف المحذوفة على الوظائف الخاصة غير المحددة." Scott Meyers: Effective Modern C++, O'REILLY,  ).
تصغير|مخطط UML في سي شارب تحتوي على منشئ ومدمر.

 في لغة سي مع ملحقات جي سي سي 
يأتي مُجمِّع سي الخاص بمجموعة مصرفات جنو مع امتدادين يسمحان بتنفيذ المُدمِّرات:

 تسمح سمة دالة destructor C "destructor" function attribute  بتحديد وظائف التدمير ذات الأولوية العالمية: عندما ترجع main() ، يتم استدعاء هذه الوظائف حسب ترتيب الأولوية قبل إنهاء العملية. انظر أيضًا: اختراق فن الاستغلال . 
 تسمح سمة متغير التنظيف بإرفاق دالة مدمرة بمتغير: يتم استدعاء الدالة عندما يخرج المتغير عن النطاق.

 زوجو 
يمكن أن تكون المدمرات في Xojo (REALbasic) في أحد شكلين. يَستخدم كل شكل إعلان طريقة عادي باسم خاص (بدون معلمات وبدون قيمة إرجاع). يستخدم النموذج الأقدم نفس اسم المخطط مع البادئة ~ (علامة التلدة). يستخدم النموذج الأحدث اسم Destructor . يُفضل استخدام الشكل الأحدث لأنه يجعل إعادة بناء لمخطط أسهل.
 Class Foobar
   // Old form
   Sub ~Foobar()
   End Sub

   // New form
   Sub Destructor()
   End Sub
 End Class

 انظر أيضا 

 المُنهي
 منشئ (علوم الكمبيوتر)
 عمر الكائن
 الاستحواذ على الموارد هو عملية تهيئة
 قاعدة الثلاثة (برمجة C++)

 مراجع 

تصنيف:سي++
تصنيف:طريقة