[英]Overalignment of an existing type in c++17
給定一個現有類型T
,可以使用alignas()
關鍵字在堆棧上過度對齊它:
alignas(1024) T variable;
對於動態分配,我們有一個繁瑣的語法:
T *variable = new (std::align_val_t(1024)) T;
但是,這種語法有兩個問題:
一種解決方法似乎是定義封裝T
的新類型:
alignas(1024)
struct AlignedType {
T _;
};
Alignedtype variable = new AlignedType; // Properly aligned in c++17
delete variable; // Suitable aligned deallocation function called in c++17
這種解決方法比較麻煩,如果T
的構造函數有參數,我們必須在轉發構造函數 arguments 中添加一些語法惡作劇,並且我們需要訪問variable._
以獲取真實內容。
Inheritance 稍微簡單一些,但如果T
是基本類型(如uint32_t
),我們就不能使用 inheritance。
我的問題如下:
做類似的事情
using AlignedType = alignas(32) T;
是可能的(以上內容無法編譯)還是無法使用自定義 alignment 動態分配現有類型而不訴諸語法復雜性?
不可能達到您假設的等價物:
using AlignedType = alignas(32) T;
不存在與另一種類型等效但具有不同 alignment 的類型。 如果語言允許這樣的東西存在,想象一下我們必須添加到語言中的所有額外的重載解決規則。
語法
new (std::align_val_t(1024)) T;
應該管用。 但是,MSVC 有一個錯誤,它認為::operator new(std::size_t, std::align_val_t)
是“布局分配函數”而不是“通常的分配函數”。 這會導致您看到的錯誤,它抱怨放置分配 function 與通常的釋放 function 匹配。
(似乎這是標准的錯誤,因為不清楚: CWG2592 。但是,MSVC 也應該受到責備;為什么他們選擇以使new (std::align_val_t(x)) T
非法的方式來解釋標准? )
一種解決方法是實現您自己的operator new
和匹配的operator delete
,將委托給您實際要調用的那些:
struct alignment_tag {};
void* operator new(std::size_t size, alignment_tag, std::align_val_t alignment) {
return operator new(size, alignment);
}
void operator delete(void* p, alignment_tag, std::align_val_t alignment) {
operator delete(p, alignment);
}
現在你可以做
T *variable = new (alignment_tag{}, std::align_val_t(1024)) T;
我個人會將其包裝為:
template <typename T, typename... Args>
std::unique_ptr<T> make_unique_aligned(std::align_val_t alignment, Args&&... args) {
return std::unique_ptr<T>(new (alignment_tag{}, alignment) T(std::forward<Args>(args)...));
}
(如果需要,您可以隨時調用.release()
。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.