【问题标题】:Pointer to std::vector of structs指向结构的 std::vector 的指针
【发布时间】:2015-11-05 21:05:42
【问题描述】:
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;

主要目标是,我可以使用 1 行/函数轻松创建指向 Struct[n] 的指针。

【问题讨论】:

  • 做这样的操作会导致指向无效迭代器的指针。
  • 您是否考虑过使用参考文献?例如Struct_t&amp; tmp = Struct[value]; tmp.Value1 = 23;。下面提到的关于悬空指针的警告仍然适用,仅在您知道向量不会被重新分配的受限范围内使用。

标签: c++ arrays pointers vector struct


【解决方案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 不是您想要使用的抽象类型。当向量需要重新调整大小(缩小或增长)时,the iterators are invalidated,因此您的指针将指向现在已释放的内存,从而使您的程序崩溃。如果你想拥有直接指向向量元素的原始指针,你首先要:

  1. 使用list 而不是vector
  2. 可能使用托管指针来处理引用计数。

最后,在处理vectorlisthash_table 等模板类时,您应该尝试习惯使用我上面使用的迭代器示例,因为您不必担心检查用于使用无效索引时的异常(重载的[] 运算符可以抛出异常,除非您将它们替换为.at() 成员函数而不是元素访问)。

【讨论】:

  • 如果中间没有 API 操作,访问容器的数据表示是完全可以的。在这种情况下,内部指针不会自行改变。
  • @GrzegorzSzpetkowski 但首先养成的习惯/风格并不安全。此外,如果 TC/OP 寻求有关如何生成指向向量元素的原始指针的帮助,他/她可能不熟悉迭代器失效,并且将来可能会咬到他们。
  • 从这个角度来看,你是对的。我假设 OP 已经掌握了一些 STL 容器的基本知识。
  • @GrzegorzSzpetkowski 够公平的。除非我试图引起他们的注意,否则我几乎从不回答 DV。如果看起来轻率,我深表歉意。
【解决方案2】:

对于 std::vector,&amp;v[i] 为您提供指向第 i 个元素的指针。您的示例代码变为:

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

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

所以单行是Struct_t* s = &amp;Struct[value];

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

是的,调整 Struct 的大小将使调整大小之前所做的任何指针无效,是的,使用迭代器通常是一种更好的技术。但这是对原问题的正确合理的回答。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 2021-02-17
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    相关资源
    最近更新 更多