[英]Create dummy object of non-default-constructible class
tl; dr:我想構造一個包含泛型類型Value成員的ListEntry類,但Value不是默認構造的, ListEntry不知道如何構造它。 我永遠不會訪問這個Value成員,所以沒有初始化它並不重要。
為什么我這樣做
我正在實現一個大致類似於以下內容的雙鏈表
template<class Value>
class ListEntry {
Value value;
ListEntry<Value> *prev;
ListEntry<Value> *next;
};
template<class Value>
class List {
ListEntry<Value> sentinel;
};
列表條目之間的鏈接總是形成一個閉合的圓圈,其中sentinel將最后一個列表元素連接到第一個列表元素。 使用sentinel.prev =&sentinel和sentinel.next =&sentinel初始化sentinel對象。
這樣,我擺脫了很多特殊情況,我永遠不必檢查nullptr,因為沒有空指針。 將元素添加到列表的末尾(在最后一個元素和sentinel之間)不是特殊情況,但與在兩個真實元素之間的列表中間添加元素相同。
因此,在所有實際列表條目中,值字段將包含列表條目的實際值。 對於它們,我可以通過在其構造函數中賦予它一個Value對象來初始化ListEntry ,因此我不需要Value是默認的可構造的。 在哨兵中,永遠不會訪問值字段。 但不幸的是,由於Value不是默認構造的,編譯器不允許我創建sentinel對象。
我可以使ListEntry中的value成員成為指針,boost :: optional或類似的東西。 由於性能問題,我不喜歡這樣。 關於如何在沒有性能/內存成本的情況下在ListEntry中存儲Value並且不需要Value可默認構造的任何想法? 在我看來,必須有一種獲取Value對象而不調用其構造函數的方法。
使用原始緩沖區和新位置:
template<class Value>
class ListEntry {
alignas(Value) char storage[sizeof(Value)];
ListEntry<Value> *prev;
ListEntry<Value> *next;
};
構建Value
:
new (entry->storage) Value(/* params */);
破壞Value
:
reinterpret_cast<Value*>(entry->storage)->~Value();
您可以將其拆分為基類和節點類,例如
class ListEntryBase {
ListEntryBase *prev;
ListEntryBase *next;
};
template<class Value>
class ListEntry : public ListEntryBase {
Value value;
};
template<class Value>
class List {
ListEntryBase sentinel;
};
這樣您就可以避免創建不需要的值,同時Value
不必是默認構造。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.