使用指针和偏移迭代通过stucts成员的向量

Bev*_*nes 3 c++ iteration pointers heap-memory

我试图通过非指针追逐优化一段代码,就像我现在一样.我想创建一个常量偏移量来添加到存储指针以获取下一个数据条目,请参阅下面的代码.但是,数据位于包含不同数据类型的类或结构中.

所以我在下面的代码片段中得到了正确的行为,即输出为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;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是双重的:

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

Max*_*hof 6

不,这不是合法的C++.仅当您保持在同一个数组(或其结束之后的一个数组)内时,才会定义指针算法.

expr.add#4

J具有整数类型的表达式添加到P指针类型的表达式或从指针类型的表达式中减去时,结果的类型为P.

  • (4.1)如果P求值为空指针值并J求值为0,则结果为空指针值.

  • (4.2)否则,如果P指向具有n个元素x[i]的数组对象的x元素,则表达式P + JJ + P(其中J具有值j)指向(可能是假设的)元素x[i+j]if 0?i+j?n和表达式P - J指向(可能是假设的)元素x[i?j]if 0?i?j?n.

  • (4.3)否则,行为未定义.

(4.1)不适用,因为你没有在nullptrs上操作.(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];
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

104字节究竟有多大foo.该[rax+24+rsi*8]表达式做所有的附加指针运算是免费的.