我正在阅读cppreference,在std::aligned_storage的示例中,有一个关于向量/数组类的示例:
基本上,每个元素所在的内存桶/区域/地址都是一个char缓冲区。在该缓冲区中存在每个元素位置处,会进行T类型的放置new操作。因此,当返回该缓冲区的位置时,可以将char缓冲区强制转换为T*,因为在那里构造了一个T对象。从C++17开始为什么需要std::launder?我已经问了很多关于这个问题的问题,似乎大家都认为:
这显然不是严格别名违规,完全没问题。那么为什么这里需要使用std::launder呢?
template<class T, std::size_t N>
class static_vector
{
// properly aligned uninitialized storage for N T's
typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N];
// IF you want to see possible implementation of aligned storage see link.
// It's very simple and small, it's just a buffer
std::size_t m_size = 0;
public:
// Create an object in aligned storage
template<typename ...Args> void emplace_back(Args&&... args)
{
if( m_size >= N ) // possible error handling
throw std::bad_alloc{};
// construct value in memory of aligned storage
// using inplace operator new
new(&data[m_size]) T(std::forward<Args>(args)...);
++m_size;
}
// Access an object in aligned storage
const T& operator[](std::size_t pos) const
{
// note: needs std::launder as of C++17
// WHY
return *reinterpret_cast<const T*>(&data[pos]);
}
// Delete objects from aligned storage
~static_vector()
{
for(std::size_t pos = 0; pos < m_size; ++pos) {
// note: needs std::launder as of C++17
// WHY?
reinterpret_cast<T*>(&data[pos])->~T();
}
}
};
基本上,每个元素所在的内存桶/区域/地址都是一个char缓冲区。在该缓冲区中存在每个元素位置处,会进行T类型的放置new操作。因此,当返回该缓冲区的位置时,可以将char缓冲区强制转换为T*,因为在那里构造了一个T对象。从C++17开始为什么需要std::launder?我已经问了很多关于这个问题的问题,似乎大家都认为:
alignas(alignof(float)) char buffer [sizeof(float)];
new (buffer) float;// Construct a float at memory, float's lifetime begins
float* pToFloat = buffer; // This is not a strict aliasing violation
*pToFloat = 7; // Float is live here
这显然不是严格别名违规,完全没问题。那么为什么这里需要使用std::launder呢?
new
返回的指针来访问创建的对象。不允许转换buffer
。但是,可以使用std::launder
从buffer
中获取有效指针。 - spectraschar buffer[32]; MyStruct * ptr = new (&buffer[0]) MyStruct{}; ptr->~MyStruct();
是可以的(假设对齐和大小要求已满足)。 - spectras