簡體   English   中英

創建非默認可構造類的虛擬對象

[英]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.

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