gpt4 book ai didi

c++ - 使用指针和偏移量迭代 stucts 成员的 vector

转载 作者:太空狗 更新时间:2023-10-29 20:20:04 44 4
gpt4 key购买 nike

我正在尝试通过不跟踪指针来优化一段代码,就像我现在所做的那样。我想创建一个常量偏移量以添加到存储的指针以获取下一个数据条目,请参见下面的代码。但是,数据位于类或结构的旁边,包含不同的数据类型。

所以我在下面的代码片段中得到了正确的行为,即输出是 1、2、3。

#include <iostream>
#include <vector>

// knows nothing about foo
class Readfoo
{
private:
int offset;
double* pdouble;

public:
void SetPoint(double* apdouble, int aoffset)
{
offset = aoffset;
pdouble = apdouble;
};

const double& printfoo(int aidouble) const
{
return *(pdouble + offset*aidouble);
};
};

// knows nothing about readFoo
struct foo
{
int a[5];
double b[10];
};

int main()
{
// populate some data (choose b [2] or other random entry.).
std::vector<foo> bar(10);
bar[0].b[2] = 1;
bar[1].b[2] = 2;
bar[2].b[2] = 3;

// access b[2] for each foo using an offset.
Readfoo newReadfoo;
newReadfoo.SetPoint(&(bar[0].b[2]), sizeof(foo)/sizeof(double));
for(int ii = 0; ii < 3; ii++)
{
std::cout<<"\n"<<newReadfoo.printfoo(ii);
}
return 0;
}

我的问题有两个方面:

  1. 这段代码是否真的合法,它是否会产生未定义的行为?
  2. 如果不合法,有没有办法在不存储实际指针的情况下,通过 foo 迭代访问 b[2],在上述情况下,使用某种形式的常量偏移量(比如在起始点之间添加位数每个数据条目的地址。)?

最佳答案

不,这不是合法的 C++。仅当您位于同一个数组(或超出数组末尾的数组)内时才定义指针算法。

expr.add#4

When an expression J that has integral type is added to or subtracted from an expression P of pointer type, the result has the type of P.

  • (4.1) If P evaluates to a null pointer value and J evaluates to 0, the result is a null pointer value.

  • (4.2) Otherwise, if P points to element x[i] of an array object x with n elements, the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i+j] if 0≤i+j≤n and the expression P - J points to the (possibly-hypothetical) element x[i−j] if 0≤i−j≤n.

  • (4.3) Otherwise, the behavior is undefined.

(4.1) 不适用,因为您没有在 nullptr 上操作。 (4.2) 不适用,因为您正在使用 double*,因此标准引号中的 x 必须是 double 数组,即 b 结构的成员。根据剩余的 (4.3),使用指针算法离开边界是未定义的行为。

你在这里试图做的正是一个好的编译器无论如何应该(并且将会)在幕后做的事情:

volatile double output;

void bar(std::vector<foo> bar, int innerOffset)
{
for (foo& f : bar)
output = f.b[innerOffset];
}

https://godbolt.org/z/S9qkTf

注意反汇编如何执行您想要的指针算法(因为编译器知道它在目标平台 上工作)。这是最内层的循环:

.L3:
movsd xmm0, QWORD PTR [rax+24+rsi*8]
add rax, 104
movsd QWORD PTR output[rip], xmm0
cmp rdx, rax
jne .L3

104 字节正是 foo 的大小。 [rax+24+rsi*8] 表达式免费执行所有额外的指针运算。

关于c++ - 使用指针和偏移量迭代 stucts 成员的 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54441263/

44 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com