以C++方式为结构和数组着色
Aliasing struct and array the C++ way
这是我另一个问题的C++跟进
在ISO C之前的旧时代,以下代码不会让任何人感到惊讶:
struct Point {
double x;
double y;
double z;
};
double dist(struct Point *p1, struct Point *p2) {
double d2 = 0;
double *coord1 = &p1->x;
double *coord2 = &p2->x;
int i;
for (i=0; i<3; i++) {
double d = coord2[i] - coord1[i]; // THE problem
d2 += d * d;
}
return sqrt(d2);
}
不幸的是,这个有问题的行使用指针算法(p[i]
根据定义*(p + i))
在任何数组之外,这是标准明确不允许的。C++17的草案4659在8.7中说:
如果表达式 P 指向具有 n 个元素的数组对象 x 的元素 x[i], 表达式 P + J 和 J + P(其中 J 的值为 j)指向(可能假设的)元素 x[i + j] 如果 0 <= i + j <= n;否则,行为是未定义的。
(非规范性)注释 86 使其更加明确:
为此目的,不是数组元素的对象被视为属于单元素数组。一个 经过 n 个元素的数组 x 的最后一个元素的指针被视为等效于指向假设元素的指针 x[n] 用于此目的。
引用问题的公认答案使用了 C 语言通过联合接受类型双关语的事实,但我永远无法在 C++ 标准中找到等价物。所以我假设一个包含匿名结构成员和一个数组的联合会导致C++Undefined Behaviour
——它们是不同的语言......
问题:
什么是循环访问结构成员的一致性方法,就好像它们是 C++ 中数组的成员一样?我正在当前(C++17)版本中寻找一种方法,但也欢迎旧版本的解决方案。
免責聲明:
它显然仅适用于相同类型的元素,并且可以通过一个简单的assert
来检测填充,如另一个问题所示,因此填充、对齐和混合类型不是我在这里的问题。
使用指向成员的指针的 constexpr 数组:
#include <math.h>
struct Point {
double x;
double y;
double z;
};
double dist(struct Point *p1, struct Point *p2) {
constexpr double Point::* coords[3] = {&Point::x, &Point::y, &Point::z};
double d2 = 0;
for (int i=0; i<3; i++) {
double d = p1->*coords[i] - p2->*coords[i];
d2 += d * d;
}
return sqrt(d2);
}
恕我直言,最简单的方法是实现operator[]
。您可以像这样创建一个帮助程序数组,或者只是创建一个开关...
struct Point
{
double const& operator[] (std::size_t i) const
{
const std::array coords {&x, &y, &z};
return *coords[i];
}
double& operator[] (std::size_t i)
{
const std::array coords {&x, &y, &z};
return *coords[i];
}
double x;
double y;
double z;
};
int main()
{
Point p {1, 2, 3};
std::cout << p[2] - p[1];
return 0;
}
struct Point {
double x;
double y;
double z;
double& operator[]( std::size_t i ) {
auto self = reinterpret_cast<uintptr_t>( this );
auto v = self+i*sizeof(double);
return *reinterpret_cast<double*>(v);
}
double const& operator[]( std::size_t i ) const {
auto self = reinterpret_cast<uintptr_t>( this );
auto v = self+i*sizeof(double);
return *reinterpret_cast<double const*>(v);
}
};
这取决于您的"结构"中的double
之间没有包装。 断言这一点很困难。
POD 结构是保证的字节序列。
编译器应该能够将[]
编译为与原始数组访问或指针算术相同的指令(或缺少指令)。可能存在一些问题,即此优化发生"太晚",无法进行其他优化,因此请仔细检查性能敏感代码。
转换为char*
或std::byte*
而不是uintptr_t
可能是有效的,但在这种情况下是否允许指针算术存在一个核心问题。
您可以使用以下事实:将指针强制转换为intptr_t
执行算术运算,然后将值转换回指针类型是实现定义的行为。我相信它将适用于大多数编译器:
template<class T>
T* increment_pointer(T* a){
return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(a)+sizeof(T));
}
这种技术是最有效的,如果使用表查找,优化器似乎无法产生最佳效果:组件比较
- 从函数中全局删除并重新实例化数组结构,而无需在编译时知道数组的大小
- 如何使用函数的输出初始化 const 数组结构字段?
- 传递数组结构、ofstream 和 interger 以运行
- 从文本文件中读取并输入到数组结构中,然后显示读取的数据C++
- 将文本文件读取到数组结构中
- C/C++中数组结构和数组结构的通用接口
- C++ MDC final-在字符类型的数组结构中按字母顺序对记录中的名称进行排序
- C++ 使用数组结构创建平衡的二叉搜索树
- C++:释放动态数组(结构成员)和指向此结构的指针的方法
- 使用 vector 在 c++ 中声明 3D 数组结构
- 数组结构无法正确打印
- 如何在C++中访问数组结构内部的数组结构
- CIN进入数组结构似乎什么也没输入
- ifstream将数组结构到txt文件中,然后尽可能将其提取为数组
- wlanapi-将WlanFreeMemory释放其WLAN_INTERFACE_INFO数组结构
- 显示数组结构 c++
- C++ 使用函数访问数组结构的方法是什么?
- 将庞大的数组结构复制到 GPU
- 如何封送包含字符矩阵的数组结构
- C++多维数组结构的对齐