لماذا لا توجد وظائف إعادة التخصيص في مخصصات C ++؟

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

  •  29-09-2019
  •  | 
  •  

سؤال

في C وظائف معالجة الذاكرة القياسية malloc(), realloc() و free(). ومع ذلك ، فإن مخصصات C ++ stdlib متوازية فقط اثنين منهم: لا توجد وظيفة إعادة التخصيص. بالطبع ، لن يكون من الممكن فعل نفس الشيء تمامًا realloc(), ، لأن ببساطة نسخ الذاكرة غير مناسب للأنواع غير المجمعة. ولكن هل ستكون هناك مشكلة مع هذه الوظيفة: على سبيل المثال:

bool reallocate (pointer ptr, size_type num_now, size_type num_requested);

أين

  • ptr تم تخصيصه مسبقًا مع نفس المخصص ل num_now أشياء؛
  • num_requested >= num_now;

والدلالات على النحو التالي:

  • إذا تمكن المخصص من توسيع كتلة الذاكرة المعينة في ptr من الحجم ل num_now الكائنات ل num_requested الكائنات ، إنها تفعل ذلك (تاركًا ذاكرة إضافية غير محددة) ويعود true;
  • وإلا فإنه لا يفعل شيئًا ويعود false.

منحت ، هذا ليس بسيطًا للغاية ، لكن المخصصين ، كما أفهم ، يكونون في الغالب مخصصة للحاويات والرمز للحاويات معقدة بالفعل بالفعل.

بالنظر إلى هذه الوظيفة ، std::vector, ، على سبيل المثال ، يمكن أن تنمو على النحو التالي (الرمز الكاذب):

if (allocator.reallocate (buffer, capacity, new_capacity))
  capacity = new_capacity;     // That's all we need to do
else
  ...   // Do the standard reallocation by using a different buffer,
        // copying data and freeing the current one

يمكن للمخصصين غير القادرين على تغيير حجم الذاكرة تمامًا تنفيذ مثل هذه الوظيفة عن طريق غير مشروط return false;.

هل هناك عدد قليل جدًا من تطبيق تخصيص تخصيص إعادة التخصيص لدرجة أنه لن يستحق كل هذا العناء؟ أم أن هناك بعض المشاكل التي أغفلتها؟

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

المحلول

من:http://www.sgi.com/tech/stl/alloc.html

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

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

نصائح أخرى

هذا هو في الواقع عيب في التصميم الذي يشير إليه Alexandrescu مع المخصصين القياسيين (وليس المشغل جديد []/حذف [] ولكن ما كان في الأصل مخصصات STL المستخدمة لتنفيذ Std :: Vector ، على سبيل المثال).

يمكن أن يحدث realloc بشكل أسرع بكثير من malloc ، memcpy ، وخالية. ومع ذلك ، في حين يمكن تغيير حجم كتلة الذاكرة الفعلية ، يمكن أيضًا نقل الذاكرة إلى موقع جديد. في الحالة الأخيرة ، إذا كانت كتلة الذاكرة تتكون من غير PODs ، فسيحتاج جميع الكائنات إلى تدميرها ونسخها بعد RealLOC.

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

STD :: Vector <...> :: الاحتياطي غير كاف: إنه يعالج حالة مختلفة حيث يمكن توقع حجم الحاوية. بالنسبة للقوائم المتغيرة بحجم متغير حقًا ، يمكن أن يجعل الحل RealLoc حاويات متجاورة مثل Std :: Vector بشكل أسرع بكثير ، خاصةً إذا كان بإمكانه التعامل مع الحالات التي يتم فيها تغيير حجم كتلة الذاكرة بنجاح دون نقلها ، وفي هذه الحالة يمكن أن يحذف نسخ الاتصال المُنشئون والمدمرون للكائنات في الذاكرة.

ما تطلبه هو ما هو في الأساس vector::reserve يفعل. دون تحريك دلالات الكائنات ، لا توجد طريقة لإعادة تخصيص الذاكرة ونقل الكائنات حولها دون القيام بنسخة وتدمير.

نظرًا للطبيعة الموجهة نحو الكائن لـ C ++ ، وإدراج أنواع الحاويات القياسية المختلفة ، أعتقد أنه ببساطة تم التركيز بشكل أقل على إدارة ذاكرة الاتجاه مقارنةً بـ C. ، لكن الضغط على علاج هذا أمر ضئيل ، حيث يمكن الحصول على جميع الوظائف الناتجة تقريبًا باستخدام الحاويات بدلاً من ذلك.

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

كان ينبغي أن يكون هناك إعادة تخصيص الصفيف:

p = renew(p) [128];

أو شيء من هذا القبيل.

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