2013-08-19 17 views
11

Trong mã C++ 03, làm cách nào để tôi portably thực hiện một bộ đệm unsigned char[sizeof(T)] có cùng kích thước và căn chỉnh giống như của một loại nhất định T?Làm cách nào để triển khai thực hiện lưu trữ ngăn xếp phù hợp trong C++ 03?

Ví dụ:

template<class T> 
void test() 
{ 
    unsigned char buffer[sizeof(T)]; // <----- how do I ensure this is aligned? 
    if (some_condition()) 
    { 
     T *const obj = new(buffer) T(); 
     // ... 
     obj->~T(); 
    } 
    else { /* use 'buffer' for something else */ } 
} 

Đây có phải là thậm chí có thể, hoặc bạn đang buộc phải sử dụng phần mở rộng trình biên dịch để thực hiện điều này?

+0

Câu hỏi thú vị. 1 để ghi nhớ để tự hit các destructor (mặc dù tôi là một chút mất mát như thế nào bạn đang làm như vậy thông qua một 'const'. Tôi thực sự cần phải chải lên trên' const' vị trí của tôi). – WhozCraig

+0

@WhozCraig: Cảm ơn. Lưu ý rằng pointee không phải là const, con trỏ chính nó là. :) – Mehrdad

+0

Vâng, tôi chỉ thấy điều đó. = P – WhozCraig

Trả lời

7

Trong cột Guru Of The Week #28, Herb Sutter sử dụng một liên minh nhưng nó ít mạnh mẽ hơn nỗ lực của Boost.

Boost's aligned_storage giải quyết các chi tiết đẫm máu cho bạn. Nếu bạn nhìn vào triển khai của nó, bạn sẽ thấy nó sử dụng __alignof của MSCV hoặc __alignof__ của GCC cũng như một mẫu khác: type_with_alignment.

Từ codebase của riêng tôi, Tôi đã từng sử dụng (có nguồn gốc từ liên kết GOTW trên):

#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 150020706) 
# pragma warning(push) 
# pragma warning(disable: 4371) 
#endif // #if (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 150020706) 
     union AlignedStorage 
     { 
     char  storage[sizeof(T)]; 
     int16  dummy0; 
     int32  dummy1; 
     int64  dummy2; 
     float  dummy3; 
     double  dummy4; 
     long double dummy5; 
     void  (*dummy6)(); 
     struct  dummy7; 
     int   dummy7::*dummy8; 
#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140050215) 
# pragma warning(push) 
# pragma warning(disable: 4121) 
#endif // #if (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140050215) 
     int   (dummy7::*dummy9)(int); 
#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140050215) 
# pragma warning(pop) 
#endif // #if (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140050215) 

     }; // AlignedStorage 
#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 150020706) 
# pragma warning(pop) 
#endif // #if (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 150020706) 

Những ngày này tôi sẽ chỉ dựa vào Boost vì nó có khả năng bao trùm nhiều hơn nữa các trường hợp góc và độ đặc hiệu trình biên dịch

+0

Hai vấn đề: (1) Tôi hỏi làm thế nào điều này được ** thực hiện ** ở nơi đầu tiên. Có một cách di động để làm điều đó hay không nó yêu cầu phần mở rộng trình biên dịch? (2) Tôi cho nó làm tham số mẫu thứ hai (căn chỉnh) là gì? – Mehrdad

+0

Sau khi chỉnh sửa # 1 - vì vậy bạn đang nói nó yêu cầu phần mở rộng trình biên dịch? – Mehrdad

+0

Sau khi chỉnh sửa # 2 - có, tôi có thể kết hợp tất cả các loại có thể để có được căn chỉnh tối đa nhưng điều chỉnh quá mức dữ liệu và lãng phí dung lượng trong nhiều trường hợp. Tôi đang cố gắng để có được ** liên kết ** giống như loại; không nhiều hơn, không ít hơn. – Mehrdad

2

Lý do mở rộng trình biên dịch như __alignof__attribute__((aligned(n)) tồn tại là việc xác định và thực thi căn chỉnh không thể được triển khai một cách hợp lý trong C và C++. I E. tiêu chuẩn không yêu cầu phải làm điều đó.

+0

Tôi không chắc chắn nếu bạn đang cố gắng để nói nó * không * thực hiện một cách ổn định, hoặc nếu nó thực sự * không thể * được thực hiện một cách ổn định. Mà một trong những bạn có ý nghĩa? – Mehrdad

+0

c/C++ tiêu chuẩn chỉ để lại tự do cho trình biên dịch, mọi thứ vẫn phải được liên kết với char ít nhất. Trong sự sắp xếp C++ 11 là một phần của tiêu chuẩn, sự liên kết có lẽ là di động đối với hầu hết các kiến ​​trúc hiện có. – GameDeveloper

+0

@Mehrdad C++ tiêu chuẩn không yêu cầu cơ sở vật chất cho điều đó, do đó các phần mở rộng. –

Các vấn đề liên quan