【发布时间】:2012-10-15 20:39:01
【问题描述】:
考虑以下类:
template <class T>
class defer {
public:
template <class ...Args>
void construct(Args&&...);
T& obj();
~defer();
private:
std::uint8_t memory[sizeof(T)];
T * ptr();
};
template <class T>
template <class ...Args>
void defer<T>::construct(Args&& ...args) {
new(static_cast<void*>(&memory[0])) T(std::forward<Args>(args)...);
}
template <class T>
T& defer<T>::obj() {
return *(ptr());
}
template <class T>
defer<T>::~defer() {
ptr()->~T();
}
template <class T>
T * defer<T>::ptr() {
return static_cast<T*>(&memory[0]);
}
现在我知道这有问题,但为了使代码简短便于讨论,我们将假设 defer::construct() 总是在对象超出范围之前被调用。
话虽如此,这样做是否总是安全的?或者在具有其他疯狂的多重虚拟继承的一些奇怪的极端情况下,std::uint8_t[sizeof(T)] 可以不分配足够的空间吗?
【问题讨论】:
-
std::uint8_t[sizeof(T)]将始终有足够的空间。但是......它可能并不总是有正确的对齐方式(std::aligned_storage可以提供帮助)。 -
uint8_t是可选。使用uint_least8_t或uint_fast8_t;它们将永远存在。 -
@Pete Becker:是的,但你知道有哪些平台没有 8 位整数类型吗?此外,我知道在某些平台上 uint_least8_t 和 uint_fast8_t 都是为了提高效率而对 int 的 typedef,这可能意味着 300% 的内存开销。
std::uint8_least8_t[sizeof(T)/sizeof(std::uint_least8_t)+((sizeof(T) % sizeof(std::uint_least8_t) != 0) ? 1 : 0)]有效,但对我来说有点难看... -
uint_least8_t必须是具有至少 8 位的无符号类型的同义词,“这样尺寸较小的无符号类型至少具有指定的宽度”。 (C 标准,7.20.1.2/2)。如果你的实现将它定义为int,当有更小的类型可用时,它不仅有错误的属性(因为它是有符号类型),而且它太大了,因此不符合标准。
标签: c++ templates c++11 placement-new