لماذا لا STD :: String :: max_size () == std :: string :: incorator :: max_size ()
سؤال
لقد لاحظت مؤخرًا أن البيان التالي غير صحيح std::string s
.
s.max_size() == s.get_allocator().max_size();
أجد هذا مثيرًا للاهتمام بشكل افتراضي std::string
سوف نستخدم std::allocator<char>
التي لها حد نظري size_type(-1)
(نعم أعلم أنني أفترض تكملة 2 ، لكن هذا لا علاقة له بالسؤال الفعلي). أعلم أن القيود العملية ستكون أقل بكثير من هذا. على نظام X86 32 بت نموذجي ، ستشغل النواة 2 جيجابايت (ربما 1 جيجا بايت) من مساحة العنوان مما يترك حد عملي أصغر بكثير.
على أي حال ، GNU LIBSTDC ++ std::basic_string<>::max_size()
يبدو أنه يعيد نفس القيمة بغض النظر عن ما يقوله المخصص الذي يستخدمه (شيء مثل 1073741820
).
لذا يبقى السؤال ، لماذا لا std::basic_string<>::max_size()
فقط العودة get_allocator().max_size()
؟ يبدو لي أن هذا هو الحد الأعلى الافتراضي. وإذا كان التخصيص قصيرًا ، فسوف يلقي فقط std::bad_alloc
, ، فلماذا لا تحاول؟
هذا فضول أكثر من أي شيء آخر ، كنت أتساءل فقط لماذا يتم تعريف الاثنين بشكل منفصل في هذا التنفيذ على الأقل.
المحلول
في Microsoft Connect تم نشر خطأ يتعلق بسؤالك. لدى Microsoft إجابة مثيرة للاهتمام:
لقد قمنا بحلها حسب التصميم وفقًا لتفسيرنا للمعيار ، وهو ما لا يفسر بوضوح الغرض المقصود لـ max_size (). يوصف مخصص MAX_SIZE () بأنه "أكبر قيمة يمكن تمريرها بشكل مفيد إلى X :: TIMAINT ()" (C ++ 03 20.1.5 [lib.allocator.requirements]/الجدول 32) ، ولكن الحاوية max_size () يوصف بأنه "حجم () لأكبر حاوية ممكنة" (23.1 [lib.container.requirements]/الجدول 65). لا شيء يصف ما إذا كان ينبغي اشتقاق حاوية max_size () من مخصص Max_Size (). لقد استمد تنفيذنا لسنوات عديدة حاوية max_size () مباشرة من مخصص Max_Size () ثم استخدم هذه القيمة لفحوصات الفائض وما إلى ذلك. التفسيرات الأخرى للمعيار ، مثل لك ، ممكنة ، ولكنها ليست صحيحة بشكل لا لبس فيه. يمكن أن تستفيد صياغة المعيار بالتأكيد من التوضيح هنا. ما لم يكن ذلك وحتى حدوث ذلك ، قررنا ترك تنفيذنا الحالي دون تغيير لسببين: (1) قد يكون العملاء الآخرون يعتمدون على سلوكنا الحالي ، (2) MAX_SIZE () لا يشتري أي شيء بشكل أساسي. على الأكثر ، يمكن للأشياء التي تستهلك المخصصين (مثل الحاويات) استخدام مخصص MAX_SIZE () للتنبؤ عند تفشل التخصيص () - ولكن ببساطة استدعاء تخصيص () هو اختبار أفضل ، لأن المخصص سيقرر إعطاء الذاكرة أم لا. يمكن للأشياء التي تستهلك الحاويات استخدام الحاوية max_size () كضمان لكيفية حجم () ، ولكن ضمان أبسط هو نطاق Size_type.
بالإضافة إلى ذلك هنا يمكنك العثور على القضية الأساسية #197. نظرت اللجنة في طلب لتحسين صياغة المعيار ، ولكن تم رفضها.
إذن إجابة سؤالك "لماذا ..؟" هل هذا المعيار لا يفسر بوضوح الغرض المقصود لـ max_size ().
نصائح أخرى
لست متأكدًا تمامًا ولكن بقدر ما أعرف std::basic_string
لا يقتصر في المعيار الحالي لتخزين السلسلة في الذاكرة المستمرة. على سبيل المثال ، قد يخزنها في عدة قطع. ثم يقتصر كل قطعة من هذا القبيل على std::allocator::max_size()
لكن المبلغ قد يكون أكبر من ذلك.
كما يبدو أن هذا هو الحال مع حاويات STL. وبعد كل شيء std::basic_string
هي حاوية.
يتمتع تطبيق GCC بتعليق على كيفية حسابهم max_size
(يتعين على المرء أن يطرح حجم كائن التدبير المنزلي الداخلي الذي يتم تخصيصه ككتلة واحدة مع السلسلة) ، ثم يضيف ذلك max_size()
يعود ربع ذلك. لا يوجد سبب منطقي ، لذلك ربما يكون مجرد هامش أمان؟ (يجب أن توفر أيضًا فئة حبل ، والتي ربما يستخدمها المرء للسلاسل الكبيرة؟)
مع VC ++ max_size()
يعيد أقل من allocator.max_size()
- ربما لحساب إنهاء الشخصية الفارغة.