簡體   English   中英

c++17 中現有類型的過度對齊

[英]Overalignment of an existing type in c++17

給定一個現有類型T ,可以使用alignas()關鍵字在堆棧上過度對齊它:

  alignas(1024) T variable;

對於動態分配,我們有一個繁瑣的語法:

  T *variable = new (std::align_val_t(1024)) T;

但是,這種語法有兩個問題:

  1. Microsoft 的編譯器發出錯誤C2956 ,盡管語法有效;
  2. 銷毀和對齊刪除似乎沒有對應的運算符。

一種解決方法似乎是定義封裝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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM