C++ std::aligned\u存储的目的是什么?
如果我理解正确,std::aligned_存储的主要优点是它管理对齐。它还可以与C++ std::aligned\u存储的目的是什么?,c++,c++11,std,C++,C++11,Std,如果我理解正确,std::aligned_存储的主要优点是它管理对齐。它还可以与memcpy()一起复制,并可与POD类型一起使用 但是 1) 默认情况下,POD类型由编译器对齐,我们可以使用#pragma pack(push,1) 2) 默认情况下,我们可以使用memcpy()复制POD(我们不应该为这个功能做任何事情) 所以我真的不明白为什么我们需要std::aligned_storage?只要您希望将内存分配与对象创建分离,就可以使用std::aligned_storage 你声称: 此外
memcpy()
一起复制,并可与POD类型一起使用
但是
1) 默认情况下,POD类型由编译器对齐,我们可以使用#pragma pack(push,1)
2) 默认情况下,我们可以使用memcpy()
复制POD(我们不应该为这个功能做任何事情)
所以我真的不明白为什么我们需要
std::aligned_storage
?只要您希望将内存分配与对象创建分离,就可以使用std::aligned_storage
你声称:
此外,它仅适用于POD类型
但事实并非如此。没有任何东西阻止std::aligned_storage
与非POD类型一起使用
提供合法的用例:
模板
类静态向量
{
//为N T正确对齐的未初始化存储
typename std::aligned_storage::type data[N];
std::size\u t m\u size=0;
...
这里的想法是,一旦构建了静态_向量
,内存将立即分配给N
类型为T
的对象,但尚未创建类型为T
的对象
你不能用一个简单的T数据[N]
数组成员,因为这会立即为每个元素运行T
的构造函数,或者如果T
不是默认可构造的,甚至不会编译。首先,#pragma
指令是不可移植的。该标准没有定义任何必须支持的强制pragma,因此每个编译器都可以自由定义它有自己的一套。但是无论您使用的是什么编译器,都需要使用std::aligned_存储
。编译器库编写者可以根据pragmas、属性或编译器扩展来定义它,但用户只需#包含
并开始使用它即可
事实上,使用对齐存储的一种常见方式是将其作为一块内存,在其中可以手动创建和销毁任何类型的其他对象。它或类似的东西可以用来实现和
为了展示其背后的思想,下面开始编写一个类似于std::optional
:
#include <type_traits>
#include <memory>
template <typename T>
class my_optional
{
private:
std::aligned_storage_t<sizeof(T), alignof(T)> m_storage;
bool m_valid;
public:
constexpr my_optional() noexcept : m_valid(false) {}
constexpr my_optional(const T& obj)
noexcept(std::is_nothrow_copy_constructible<T>::value)
: m_valid(false)
{
new(static_cast<void*>(&m_storage)) T(obj);
m_valid = true;
}
constexpr const T& operator*() const
{
return *static_cast<const T*>(static_cast<const void*>(&m_storage));
}
constexpr T& operator*()
{
return *static_cast<T*>(static_cast<void*>(&m_storage));
}
~my_optional()
{
if (m_valid)
operator*().~T();
}
// Much more, to obey the Rule Of Five and add more functionality...
};
#包括
#包括
模板
我的课程是可选的
{
私人:
标准::对齐存储\u t m\u存储;
布尔m_有效;
公众:
constexpr my_optional()noexcept:m_valid(false){
constexpr my_可选(const T&obj)
noexcept(std::is\u nothrow\u copy\u constructible::value)
:m_有效(错误)
{
新的(静态铸造和存储)T(obj);
m_valid=true;
}
常量表达式常量T&运算符*()常量
{
返回*static_cast(static_cast(&m_storage));
}
constexpr T&运算符*()
{
返回*static_cast(static_cast(&m_storage));
}
~my_可选()
{
如果(m_有效)
运算符*().~T();
}
//更重要的是,要遵守五原则并添加更多功能。。。
};
std::aligned_storage
管理对齐的存储。是否在存储中放置POD或非POD对象无关紧要
std::aligned_storage
的目的是提供一个标准化的更高级别实用程序来管理对齐的存储,这样您就可以用更少的麻烦编写更干净的代码。。另一种选择是char[]
但这将/可能不会正确对齐,因为语言无法知道您想要在其中构建什么样的内容。所有这些都回答了OP的“疑问”:
#include <type_traits>
#include <memory>
template <typename T>
class my_optional
{
private:
std::aligned_storage_t<sizeof(T), alignof(T)> m_storage;
bool m_valid;
public:
constexpr my_optional() noexcept : m_valid(false) {}
constexpr my_optional(const T& obj)
noexcept(std::is_nothrow_copy_constructible<T>::value)
: m_valid(false)
{
new(static_cast<void*>(&m_storage)) T(obj);
m_valid = true;
}
constexpr const T& operator*() const
{
return *static_cast<const T*>(static_cast<const void*>(&m_storage));
}
constexpr T& operator*()
{
return *static_cast<T*>(static_cast<void*>(&m_storage));
}
~my_optional()
{
if (m_valid)
operator*().~T();
}
// Much more, to obey the Rule Of Five and add more functionality...
};