ما هي ضمانات المحاذاة التي يمكنني توقعها للصفائف في البنية؟

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

سؤال

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

للقيام بذلك، "أعلنهم" في صفي مثل هذا:

template <class K, class V> class MyClass
{
public:
   MyClass() : wereConstructorsCalled(false) {/* empty */}
   ~MyClass() {if (wereConstructorsCalled) MyCallPlacementDestructorsFunc();}

   [...]

private:
   bool wereConstructorsCalled;
   mutable char keyBuf[sizeof(K)];
   mutable char valBuf[sizeof(V)];
};

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

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

سؤالي هو، هل سيتم محاذاة مصفوفتي keyBuf و valBuf بشكل صحيح في جميع الحالات، أم أن هناك بعض الخطوات الإضافية التي يجب علي اتخاذها للتأكد من أنها ستتم محاذاتها بشكل صحيح؟(إذا كان الأمر كذلك، فسيكون من الأفضل اتخاذ خطوة لا تعتمد على النظام الأساسي)

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

المحلول

وليس هناك ضمان أن عليك الحصول على المحاذاة المناسبة. وبشكل عام مضمونة صفائف إلا أن الانحياز لنوع الأعضاء. تتماشى هناك مجموعة char لتخزين char.

والاستثناء الوحيد هو أن يمنح char وunsigned char صفائف المخصصة مع new القصوى المحاذاة، بحيث يمكنك تخزين أنواع التعسفية فيها. ولكن هذا الضمان لا ينطبق في الحالة الخاصة بك كما كنت تجنب تخصيص الكومة.

وTR1 وC ++ 0X إضافة بعض أنواع مفيدة جدا على الرغم من:

وstd::alignment_of وstd::aligned_storage معا أعطيك جوابا المحمولة (وتعمل).

وstd::alignment_of<T>::value يعطيك المواءمة المطلوبة لنوع من T. std::aligned_storage<A, S>::type يعطيك نوع POD مع A التوافق وحجم S. وهذا يعني أنه يمكنك بأمان إرسال الكائن إلى متغير من نوع std::aligned_storage<A, S>::type.

و(في TR1، مساحة الاسم هو std::tr1، بدلا من std فقط)

نصائح أخرى

هل لي أن أسأل لماذا كنت تريد أن تضع لهم في منطقة عازلة شار؟ لماذا لا مجرد إنشاء كائنات المؤشر من K و V ثم مثيل عندما كنت في حاجة إليها.

وربما لم أفهم سؤالك، ولكن لا يمكن أن عليك أن تفعل char *keyBuf[..size..];، تعيين في البداية إلى NULL (غير المخصصة) وتخصص هذه هي المرة الأولى كنت في حاجة إليها؟

وما نحاول القيام به مع وضع يبدو الأعمال الجديدة والسيئة محفوفة بالمخاطر الترميز النمط.

وعلى أي حال، والمحاذاة كود هو التنفيذ التابع.

إذا كنت تريد تغيير محاذاة التعليمات البرمجية، فاستخدم حزمة pragma

#pragma pack(push,x)

// class code here

#pragma pack(pop) // to restore original pack value

إذا كانت x تساوي 1، فلن يكون هناك حشوة بين العناصر الخاصة بك.

هنا رابط للقراءة

http://www.cplusplus.com/forum/general/14659/

لقد وجدت هذه الإجابة التي نشرها SiCrane في http://www.gamedev.net/community/forums/topic.asp?topic_id=455233 :

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

يبدو أن الاتحاد قد يقوم بالخدعة!

وأوصي بأن نظرتم الى قالب boost::optional. وهو يفعل ما تحتاج إليه، حتى لو كنت لا يمكن استخدامه ربما يجب عليك النظر في تنفيذها.

ويستخدم alignment_of وtype_with_alignment لإجراء العمليات الحسابية انحيازها والضمانات.

لجعل قصة طويلة جدا جدا جدا قصيرة جدا وهذا ما لن يساعد أدائك أي وسوف تسبب الكثير من الصداع وأنه لن يكون قبل فترة طويلة كنت الانزلاق الى كتابة managemer الذاكرة الخاصة بك.

وموضع جديد على ما يرام لPOD (ولكن لن ينقذ أي شيء) ولكن إذا كان لديك منشئ على الإطلاق ثم انها لن تعمل على الإطلاق.

وأنت أيضا لا يمكن أن تعتمد على قيمة متغير منطقية إذا كنت تستخدم وضع جديد.

والتنسيب له استخدامات جديدة ولكن ليس حقا لذلك.

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