mar*_*ack 5 c++ strict-aliasing c++11
我正在使用std::aligned_storage变体模板作为后备存储.问题是,一旦我-O2在gcc上启用,我就会开始收到"取消引用类型 - 惩罚指针会打破严格别名"的警告.
真实模板要复杂得多(在运行时检查类型),但生成警告的最小示例是:
struct foo
{
std::aligned_storage<1024> data;
// ... set() uses placement new, stores type information etc ...
template <class T>
T& get()
{
return reinterpret_cast<T&>(data); // warning: breaks strict aliasing rules
}
};
Run Code Online (Sandbox Code Playgroud)
我很确定boost::variant与此基本上是一样的,但我似乎无法找到他们如何避免这个问题.
我的问题是:
aligned_storage以这种方式使用违反严格别名,我应该如何使用它?get()因为函数中没有其他基于指针的操作?
get()被内联呢?get() = 4; get() = 3.2?由于int和float不同的类型,该序列可以重新排序吗?std::aligned_storage是的一部分<type_traits>; 与该头文件的大多数其他居民一样,它只是某些typedef的持有者,并不打算用作数据类型.它的工作是采用尺寸和对齐方式,并使您成为具有这些特征的POD类型.
你不能std::aligned_storage<Len, Align>直接使用.您必须使用std::aligned_storage<Len, Align>::type转换后的类型,它是"POD类型,适合用作任何大小最多Len且对齐为除数的对象的未初始化存储Align." (Align默认为大于或等于的最大有用对齐Len.)
正如C++标准所指出的那样,返回的类型通常std::aligned_storage是unsigned char带有对齐说明符的数组(具有指定大小).这避免了"无严格别名"规则,因为字符类型可能是任何其他类型的别名.
所以你可以这样做:
template<typename T>
using raw_memory = typename std::aligned_storage<sizeof(T),
std::alignment_of<T>::value>::type;
template<typename T>
void* allocate() { return static_cast<void*>(new raw_memory<T>); }
template<typename T, typename ...Arg>
T* maker(Arg&&...arg) {
return new(allocate<T>()) T(std::forward<Arg>(arg)...);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
685 次 |
| 最近记录: |