指向 std::vector 的结构体指针

5
struct Struct_t {
    int Value1;
    int Value2;
};

vector<Struct_t> Struct;
Struct.resize(10, Struct_t());

for (int i = 0; i < 10; ++i)
{    
    Struct[i].Value1 = (i + 10) * 3;
    Struct[i].Value2 = (i + 5) * 2;
}

我该如何创建指向Struct[i]的指针?

我想做的基本上是这样的,但我相信这可以更好地完成:

int value = 6;
Struct_t temp = Struct[value], *s;
s = &temp;

s->Value1 = 42;
s->Value2 = 6;

我的主要目标是能够用一行代码或函数轻松地创建对Struct [n]的指针。


执行这样的操作将导致指向无效迭代器的指针。 - Cloud
1
你考虑过使用引用吗?例如 Struct_t& tmp = Struct[value]; tmp.Value1 = 23;。下面提到的有关悬空指针的警告仍然适用,只在你知道向量不会被重新分配的受限范围内使用它。 - Ulrich Eckhardt
2个回答

1
到目前为止,提供的答案忽略了房间里的大象。你可以像这样创建一个指向向量元素的指针:

(容易出错的) 代码清单


#include <iostream>
#include <vector>

struct Struct_t {
    int Value1;
    int Value2;
};

int main(void)
{
    std::vector<Struct_t> sVec;
    sVec.resize(10, Struct_t());

    int count = 0;
    for (std::vector<Struct_t>::iterator vIt = sVec.begin(); vIt != sVec.end(); ++vIt)
    {    
        vIt->Value1 = (count + 10) * 3;
        vIt->Value2 = (count + 5) * 2;
        count++;
    }

    Struct_t* pStruct = &sVec[5];

    std::cout << "sVec[5] = (" << pStruct->Value1 << "," << pStruct->Value2
        << ")" << std::endl;

    return 0;
}

示例输出


sVec[5] = (45,20)

然而,如果您将生成指向vector /“数组”的单个元素的指针,则vector不是您想使用的抽象类型。当需要调整向量大小(缩小或增大)时,迭代器被使无效, 因此,您的指针将指向现在已释放的内存,导致程序崩溃。如果您想直接获得指向向量元素的原始指针,您需要首先:
  1. 使用list而不是vector
  2. 可能使用托管指针来处理引用计数。
最后,当处理像vectorlisthash_table等模板类时,您应该尝试使用我上面使用的迭代器示例,这样您就不必担心在使用无效索引时检查异常(重载的[]运算符可能会抛出异常,除非您替换为.at()成员函数进行元素访问)。

如果在容器中没有 API 操作,访问数据表示是完全可以的。在这种情况下,内部指针不会自行更改,这是完全正常的。 - Grzegorz Szpetkowski
@GrzegorzSzpetkowski 但这不是一个安全的习惯/风格,首先就不应该养成。此外,如果TC/OP正在寻求如何生成指向向量元素的原始指针的帮助,他/她可能不熟悉迭代器失效,并且这可能会在将来给他们带来麻烦。 - Cloud
从那个角度来看,你是正确的。我假设OP已经有了一些STL容器的基本知识。 - Grzegorz Szpetkowski
@GrzegorzSzpetkowski 好的,我几乎从不对答案进行 DV,除非我想引起注意。如果我的回复看起来轻率,请接受我的道歉。 - Cloud

0

对于一个 std::vector,&v[i] 会给你第 i 个元素的指针。你的示例代码变成了:

int value = 6;
Struct_t* s = &Struct[value];

s->Value1 = 42;
s->Value2 = 6;

那么这个一行代码是 Struct_t* s = &Struct[value];

这样做没有任何问题,但像 C++ 的大多数方面一样,你需要理解自己在做什么。上面的代码是完全有效的,并被标准保证。(还要注意,本答案中的代码避免了原始代码中 s 是指向临时副本的指针,并且未对 Struct 向量的内容进行更改的错误。)

是的,重新调整大小会使之前进行的任何指针失效,而使用迭代器通常是更好的技术。但这是对原始问题的正确和合理的回答。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接