C++ 使用结构成员作为数组,可移植的方式?
我有以下结构(让我们把这个1类型的例子作为一个简单的例子): 根据它的说法,一般来说,如果没有填充,你可以这样写:C++ 使用结构成员作为数组,可移植的方式?,c++,C++,我有以下结构(让我们把这个1类型的例子作为一个简单的例子): 根据它的说法,一般来说,如果没有填充,你可以这样写: int main() { Vector v{ 32.0, 42.0, 68.0 }; double* d = &v.x_; for( int i = 0; i < 3; ++i ){ std::cout << d[ i ] << ", "; } return 0; }
int main()
{
Vector v{ 32.0, 42.0, 68.0 };
double* d = &v.x_;
for( int i = 0; i < 3; ++i ){
std::cout << d[ i ] << ", ";
}
return 0;
}
我要写一个像这样的函子
//VectorComponent is an enum class, I will spare the reader the details.//
template< VectorComponent ComponentSelectorConstant >
struct GetComponent
{
const double& ComponentConstant;
GetComponent( const Vector& vector ) :
ComponentConstant( ( &vector.x_ )[ static_cast< size_t >( ComponentSelectorConstant ) ] ) {
}
operator const double&() {
return ComponentConstant;
}
};
也因为POD的概念发生了变化,以前的C++标准(包括POD和
E1[E2]
与表达式*(E1+E2)
[除了求值顺序(自C++17以来)]完全相同,即指针操作数(可能是数组到指针转换的结果,必须指向某个数组的某个元素或超过该数组末尾的某个元素)根据指针算术的规则,调整为指向同一数组的另一个元素,然后取消引用
struct
的成员不是数组的一部分,因此不能从指向另一个的指针派生指向其中一个的指针
在某些情况下,这些规则将允许您获取一个指针,该指针既不可取消引用,又同时包含同一类型的实际对象的地址。当一个指针超过结束指针时,可能会发生这种情况。但即使在这些情况下,也不能使用该指针访问该地址处的对象。如何获得指针很重要。如果您非法获取它,您可能会破坏编译器做出的导致意外行为的假设。这些都是允许编译器基于代码不会违反语言规则的信念做出的假设。无论
结构的内存布局如何,指针算法都禁止这种策略。本例中的相关规则是():
内置的下标表达式E1[E2]
与表达式*(E1+E2)
[除了求值顺序(自C++17以来)]完全相同,即指针操作数(可能是数组到指针转换的结果,必须指向某个数组的某个元素或超过该数组末尾的某个元素)根据指针算术的规则,调整为指向同一数组的另一个元素,然后取消引用
struct
的成员不是数组的一部分,因此不能从指向另一个的指针派生指向其中一个的指针
在某些情况下,这些规则将允许您获取一个指针,该指针既不可取消引用,又同时包含同一类型的实际对象的地址。当一个指针超过结束指针时,可能会发生这种情况。但即使在这些情况下,也不能使用该指针访问该地址处的对象。如何获得指针很重要。如果您非法获取它,您可能会破坏编译器做出的导致意外行为的假设。这些是允许编译器基于代码不会违反语言规则的信念而做出的假设
一般来说,如果没有填充,您可以这样写:
int main()
{
Vector v{ 32.0, 42.0, 68.0 };
double* d = &v.x_;
for( int i = 0; i < 3; ++i ){
std::cout << d[ i ] << ", ";
}
return 0;
}
看起来可能是这样,但我们不能,因为指针算术的行为是未定义的
但是,如果结构是这样写的,会发生什么
struct alignas( double ) Vector {
double x_, y_, z_;
};
struct alignas( double ) Vector
没有区别。该类已经具有该对齐要求,并且该对齐方式无论如何都不会影响指针算法的有效性
我要写一个像这样的函子
//VectorComponent is an enum class, I will spare the reader the details.//
template< VectorComponent ComponentSelectorConstant >
struct GetComponent
{
const double& ComponentConstant;
GetComponent( const Vector& vector ) :
ComponentConstant( ( &vector.x_ )[ static_cast< size_t >( ComponentSelectorConstant ) ] ) {
}
operator const double&() {
return ComponentConstant;
}
};
出于同样的原因,该函子仍然有UB,因此它没有用处
使用结构成员作为数组,可移植的方式
可移植的方法是将阵列用作阵列:
struct Vector : std::array<double, 3> {};
结构向量:std::array{};
一般来说,如果没有填充,您可以这样写:
int main()
{
Vector v{ 32.0, 42.0, 68.0 };
double* d = &v.x_;
for( int i = 0; i < 3; ++i ){
std::cout << d[ i ] << ", ";
}
return 0;
}
看起来可能是这样,但我们不能,因为指针算术的行为是未定义的
但是,如果结构是这样写的,会发生什么
struct alignas( double ) Vector {
double x_, y_, z_;
};
struct alignas( double ) Vector
没有区别。该类已经具有该对齐要求,并且该对齐方式无论如何都不会影响指针算法的有效性
我要写一个像这样的函子
//VectorComponent is an enum class, I will spare the reader the details.//
template< VectorComponent ComponentSelectorConstant >
struct GetComponent
{
const double& ComponentConstant;
GetComponent( const Vector& vector ) :
ComponentConstant( ( &vector.x_ )[ static_cast< size_t >( ComponentSelectorConstant ) ] ) {
}
operator const double&() {
return ComponentConstant;
}
};
出于同样的原因,该函子仍然有UB,因此它没有用处
使用结构成员作为数组,可移植的方式 可移植的方法是将阵列用作阵列:
struct Vector : std::array<double, 3> {};
结构向量:std::array{};
< /代码>即使没有填充,元素也完全是