std :: tuple内存对齐 [英] std::tuple memory alignment
问题描述
对于元组的伪成员,布局和内存对齐是否有正式规范?
有没有修改元组中类型的内存对齐?是否通过#pragma pack()指令实现?
例如:
typedef std :: tuple< uint8_t,uint32_t> myTuple;
有没有说明这将在内存中相同的规格:
#pragma pack()//默认包装
struct myStruct
{
uint8_t first;
uint32_t second;
}
如果这是一个愚蠢的问题,但我不完全理解对齐,
目前我有一些类似于...
#pragma pack(push)
#pragma pack(4)
struct cTriangle
{
uint32索引[3];
};
#pragma pack(pop)
template< class T>
inline bool Read(cFileStream& fStream,std :: vector< T>& vec)
{
if(!vec.size())
return true;
// fStream.Read(void * pBuffer,size_t Size)
//只是一个包装二进制ifstream真的
return fStream.Read(& vec [0] ,sizeof(T)* vec.size());
}
std :: vector< cVector3> vPoint;
vPoint.resize(Verticies);
bool result = Read(FileStream,vPoint);
如果我想将typedef cTriangle
code> std :: tuple< uint32,uint32,uint32> 为了元编程目的,我仍然能够读/写元组的原始内存(因此元组的向量)或者那个内存有未知的对齐方式?
元组通常不是标准布局,因为标准布局类一个类在其非静态数据成员的继承层次结构中,实现变量 tuple
的典型方法是通过递归继承,每个递归级别都添加一个数据成员。这允许 tuple
实现通过空基类优化来清除不同的空成员,这不能用于 struct
成员。
如果您检查 sizeof(myTuple)== sizeof(myStruct)
,您有理由假设元组的内存布局以一些(一致的)顺序包含结构的元素,但是实际上依赖于别名的元素可能会导致未定义的行为。
假设你只需要使用 tuple
的别名来进行元编程,那么最好使用元编程库,例如 Boost.Fusion ,它允许用其成员来注释struct类型:
pragma pack(push)
#pragma pack(4)
struct cTriangle {
uint32 Index [3];
};
#pragma pack(pop)
BOOST_FUSION_ADAPT_STRUCT(
cTriangle,
(uint32 [3],Index))
Is there any formal specification for the layout and memory alignment for the pseudo members of a tuple?
Is there anyway to modify the memory alignment of types in a tuple? Is it effected by a #pragma pack() directive?
For example:
typedef std::tuple<uint8_t, uint32_t> myTuple;
Is there any specification that says this will be in memory the same as:
#pragma pack() // Default packing
struct myStruct
{
uint8_t first;
uint32_t second;
}
Apologies if this is a stupid question but I don't entirely understand alignment when it comes to templates.
Edit: Example of what I'm trying to accomplish
Currently I have something along the lines of...
#pragma pack(push)
#pragma pack(4)
struct cTriangle
{
uint32 Index[3];
};
#pragma pack(pop)
template <class T>
inline bool Read(cFileStream& fStream, std::vector<T>& vec)
{
if (!vec.size())
return true;
// fStream.Read(void* pBuffer, size_t Size)
// Just a wrapper around a binary ifstream really
return fStream.Read(&vec[0], sizeof(T) * vec.size());
}
std::vector<cVector3> vPoint;
vPoint.resize(Verticies);
bool result = Read(FileStream, vPoint);
If I wanted to typedef cTriangle
as std::tuple<uint32, uint32, uint32>
for metaprogramming purposes would I still be able to read/write to the raw memory of the tuple (and thus a vector of tuples) or would that memory have unknown alignment?
Tuples are typically not standard-layout, because standard-layout classes can have at most one class in their inheritance hierarchy with non-static data members, and the typical way to implement variadic tuple
is through recursive inheritance, with each level of recursion adding one data member. This allows tuple
implementations to elide distinct empty members through the empty base class optimisation, which is not available for struct
members.
If you check that sizeof(myTuple) == sizeof(myStruct)
, you are reasonably entitled to assume that the memory layout of the tuple contains the elements of the struct in some (consistent) order, but actually relying on that for aliasing will likely cause undefined behaviour.
If as you say you just want alias with tuple
for metaprogramming, you'd be better off using a metaprogramming library such as Boost.Fusion that allows you to annotate the struct type with its members:
#pragma pack(push)
#pragma pack(4)
struct cTriangle {
uint32 Index[3];
};
#pragma pack(pop)
BOOST_FUSION_ADAPT_STRUCT(
cTriangle,
(uint32[3], Index))
这篇关于std :: tuple内存对齐的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!