अच्छी तरह से जमीन पर एक मूर्खतापूर्ण पहली पोस्ट क्या हो सकता है के लिए अग्रिम क्षमा करें। हालांकि इस विषय पर बहुत सारी सामग्री है, लेकिन इसमें से बहुत कम मेरे लिए निश्चित और/या समझदार है।सी ++: सख्त एलियासिंग बनाम यूनियन दुरुपयोग
मेरे पास AlignedArray
टेम्पलेट क्लास है जो मनमाने ढंग से संरेखण के साथ ढेर पर स्मृति आवंटित करने के लिए है (मुझे AVX असेंबली दिनचर्या के लिए 32-बाइट संरेखण की आवश्यकता है)। इसके लिए कुछ बदसूरत सूचक हेरफेर की आवश्यकता है।
एग्नेर फोग cppexamples.zip में एक नमूना वर्ग प्रदान करता है जो ऐसा करने के लिए एक संघ का दुरुपयोग करता है (http://www.agner.org/optimize/optimization_manuals.zip)। हालांकि, मुझे पता है कि एक संघ के एक सदस्य को लिखना और फिर यूबी में दूसरे परिणामों से पढ़ना।
AFAICT किसी भी सूचक प्रकार को char *
पर उपनाम करना सुरक्षित है, लेकिन केवल एक दिशा में। यह वह जगह है जहां मेरी समझ अस्पष्ट हो जाती है।
template <typename T, size_t alignment = 32>
class AlignedArray
{
size_t m_size;
char * m_unaligned;
T * m_aligned;
public:
AlignedArray (size_t const size)
: m_size(0)
, m_unaligned(0)
, m_aligned(0)
{
this->size(size);
}
~AlignedArray()
{
this->size(0);
}
T const & operator [] (size_t const i) const { return m_aligned[i]; }
T & operator [] (size_t const i) { return m_aligned[i]; }
size_t const size() { return m_size; }
void size (size_t const size)
{
if (size > 0)
{
if (size != m_size)
{
char * unaligned = 0;
unaligned = new char [size * sizeof(T) + alignment - 1];
if (unaligned)
{
// Agner:
/*
union {
char * c;
T * t;
size_t s;
} aligned;
aligned.c = unaligned + alignment - 1;
aligned.s &= ~(alignment - 1);
*/
// Me:
T * aligned = reinterpret_cast<T *>((reinterpret_cast<size_t>(unaligned) + alignment - 1) & ~(alignment - 1));
if (m_unaligned)
{
// Agner:
//memcpy(aligned.c, m_aligned, std::min(size, m_size));
// Me:
memcpy(aligned, m_aligned, std::min(size, m_size));
delete [] m_unaligned;
}
m_size = size;
m_unaligned = unaligned;
// Agner:
//m_aligned = aligned.t;
// Me:
m_aligned = aligned;
}
return;
}
return;
}
if (m_unaligned)
{
delete [] m_unaligned;
m_size = 0;
m_unaligned = 0;
m_aligned = 0;
}
}
};
तो जो विधि सुरक्षित है (आर): यहाँ मेरी AlignedArray
वर्ग के एक संक्षिप्त संस्करण (अनिवार्य रूप से Agner के एक फिर से लिखने, मेरी समझ में मदद करने के लिए) है?
के बजाय 'निर्माण char' वस्तुओं और फिर कास्ट' ऑपरेटर new' से कि टी करने के लिए, तुम क्यों कच्चे स्मृति हड़पने नहीं है (:
यहाँ के साथ सुझाव दिया तय अपने कार्य का एक संस्करण है , या यहां तक कि 'malloc'),' void * 'के रूप में, और वास्तव में इसमें' टी 'ऑब्जेक्ट्स का निर्माण करते हैं? असल में: यदि आप टी वस्तुओं चाहते हैं, टी वस्तुओं का निर्माण। इस उपयोग के मामले (गठबंधन सरणी) * शून्य * एलियासिंग चाल/यूनियन/memcpy/जो कुछ भी के लिए की जरूरत है। –
@ आर। मार्टिनिन्हो फर्नांडीस: इसके अलावा, 'शून्य * 'पर गणित की अनुमति नहीं है। आप एक गठबंधन 'शून्य * 'कैसे प्राप्त करते हैं? – Omnifarious
@ ओम्निफायरस आखिरी मैंने चेक किया, गणित को 'char *' पर भी अनुमति नहीं है। (और यदि यह भी था, तो इसका मतलब यह नहीं होगा कि आपको चार वस्तुओं का निर्माण करने और टी वस्तुओं का निर्माण करने की आवश्यकता नहीं है) आपको गणित करने के लिए पूर्णांक की आवश्यकता है। सी ++ 11 में पोर्टेबल समाधान http://en.cppreference.com/w/cpp/memory/align है। सैद्धांतिक रूप से पोर्टेबल समाधान एक संख्यात्मक प्रकार को reinterpret_cast करना है, गणित करें, और reinterpret_cast वापस करें। (यह अभ्यास में काफी पोर्टेबल है क्योंकि सभी कार्यान्वयनों में मुझे पता है कि संख्यात्मक प्रकारों के लिए reinterpret_cast अपेक्षित व्यवहार करता है) –