【发布时间】:2014-06-24 10:43:00
【问题描述】:
我正在创建一个可以存储 Atom<T> 对象的通用 AtomManager<T> 容器。
enum State { Alive, Dead, Unused };
template<class T> struct Atom
{
T impl;
int index, counter;
State state;
};
我希望 impl 不在堆上,因为我会将 Atom<T> 实例连续存储在管理器中。
AtomManager<T> 将原子存储在 std::vector<Atom<T>> 中,如下所示:
| A | A | A | A | A | A | U | U | U | U |
其中A 表示活着,U 表示未使用。当用户调用AtomManager<T>::refresh()时,所有state等于State::Dead的原子将被移动到存储的末尾,然后它们将被设置为State::Unused。示例:
| A | A | A | A | A | A | U | U | U | U |
// some atoms die
| A | D | A | D | A | A | U | U | U | U |
// user calls refresh()
| A | A | A | A | U | U | U | U | D | D |
// after refresh()
| A | A | A | A | U | U | U | U | U | U |
为了创建原子,我有一个与 T 构造函数签名匹配的函数,这要归功于可变参数模板,并在从存储开头开始的第一个未使用的原子中构造 T。
问题是T 必须是default-constructible(因为我在std::vector 上调用resize())。但这是我不需要的,因为我只关心Atom<T>::impl 当状态为State::Alive 或State::Dead 时。如果原子是活的还是死的,这意味着用户之前使用前面提到的可变参数函数构造了它。
然而,当原子未被使用时,我确实关心Atom<T>::index 和Atom<T>::counter(而Atom<T>::impl 是垃圾)。
我不关心原子未使用时Atom<T>::impl的状态。
但是,编译器可以。当T 不是默认可构造时,我不能使用AtomManager<T>。
我尝试在Atom<T> 中使用联合:
union { T impl; char dummy; };
...但我无法让它正常工作。
如何在Atom<T> 中存储T 未构造的未初始化实例?
我不关心它的状态。我确信我会在访问它之前正确构建它。但是当原子未使用时,我希望它处于未定义状态。
实现此目的的最佳方法是什么?我不希望 Atom<T>::impl 存储在堆上。
我不想引入额外的依赖项。我不需要查询Atom<T>::impl 的状态,因为我知道什么时候可以安全访问它。
【问题讨论】:
-
@MikeSeymour:我不想在项目中引入boost依赖,也不需要检查
Atom<T>::impl是否被初始化。我知道什么时候我可以正确访问它,或者什么时候它应该只是垃圾。 -
BYTE[sizeof(T)] + 新展示位置?
-
顺便说一句,如果你选择那个技巧,你应该使用
std::aligned_storage而不是字节数组。 -
std::aligned_storage<T>::type是一个保证与T适当对齐的 POD。普通字节数组不保证这一点。
标签: c++ class memory c++11 initialization