[英]Create dummy object of non-default-constructible class
tl;dr: I want to construct a class ListEntry containing a member of a generic type Value , but Value is not default constructible and ListEntry doesn't know how to construct it. tl; dr:我想构造一个包含泛型类型Value成员的ListEntry类,但Value不是默认构造的, ListEntry不知道如何构造它。 I will never access this Value member, so it doesn't matter that it isn't initialized.
我永远不会访问这个Value成员,所以没有初始化它并不重要。
Why I'm doing this 为什么我这样做
I'm implementing a double linked list roughly similar to the following 我正在实现一个大致类似于以下内容的双链表
template<class Value>
class ListEntry {
Value value;
ListEntry<Value> *prev;
ListEntry<Value> *next;
};
template<class Value>
class List {
ListEntry<Value> sentinel;
};
The links between the list entries always form a closed circle where the sentinel connects the last list element to the first list element. 列表条目之间的链接总是形成一个闭合的圆圈,其中sentinel将最后一个列表元素连接到第一个列表元素。 The sentinel object is initialized with sentinel.prev = &sentinel and sentinel.next = &sentinel.
使用sentinel.prev =&sentinel和sentinel.next =&sentinel初始化sentinel对象。
This way, I get rid of a lot of special cases and I never have to check for nullptr because there are no null pointers. 这样,我摆脱了很多特殊情况,我永远不必检查nullptr,因为没有空指针。 Adding an element to the end of the list (between the last element and the sentinel) is not a special case but the same as adding an element to the middle of the list between two real elements.
将元素添加到列表的末尾(在最后一个元素和sentinel之间)不是特殊情况,但与在两个真实元素之间的列表中间添加元素相同。
So in all real list entries, the value field will contain the actual value of the list entry. 因此,在所有实际列表条目中,值字段将包含列表条目的实际值。 For them, I can initialize ListEntry by giving it a Value object in its constructor, so I don't need Value to be default constructible.
对于它们,我可以通过在其构造函数中赋予它一个Value对象来初始化ListEntry ,因此我不需要Value是默认的可构造的。 In the sentinel, the value field will never be accessed.
在哨兵中,永远不会访问值字段。 But unfortunately, since Value is not default constructible, the compiler doesn't let me create the sentinel object.
但不幸的是,由于Value不是默认构造的,编译器不允许我创建sentinel对象。
I could make the value member in ListEntry a pointer, boost::optional or something similar. 我可以使ListEntry中的value成员成为指针,boost :: optional或类似的东西。 I don't like this due to performance issues though.
由于性能问题,我不喜欢这样。 Any ideas on how to store Value in ListEntry without performance/memory costs and without needing Value to be default constructible?
关于如何在没有性能/内存成本的情况下在ListEntry中存储Value并且不需要Value可默认构造的任何想法? It seems to me like there must be a way of getting a Value object without calling its constructors.
在我看来,必须有一种获取Value对象而不调用其构造函数的方法。
Use a raw buffer and placement new : 使用原始缓冲区和新位置:
template<class Value>
class ListEntry {
alignas(Value) char storage[sizeof(Value)];
ListEntry<Value> *prev;
ListEntry<Value> *next;
};
Constructing the Value
: 构建
Value
:
new (entry->storage) Value(/* params */);
Destructing the Value
: 破坏
Value
:
reinterpret_cast<Value*>(entry->storage)->~Value();
You can split this into a base class and a node class, eg 您可以将其拆分为基类和节点类,例如
class ListEntryBase {
ListEntryBase *prev;
ListEntryBase *next;
};
template<class Value>
class ListEntry : public ListEntryBase {
Value value;
};
template<class Value>
class List {
ListEntryBase sentinel;
};
This way you avoid creating an unneeded value and at the same time Value
need not be default constructible. 这样您就可以避免创建不需要的值,同时
Value
不必是默认构造。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.