【问题标题】:Pointer to object in vector sometimes points to a different object in the vector指向向量中对象的指针有时指向向量中的不同对象
【发布时间】:2020-03-08 20:12:41
【问题描述】:

在下面的代码中,Struct2 中的 Struct1 指针应该始终指向 Struct1 的某个对象。这些结构中的每一个都包含在一个向量中。

但是,当我输出 Struct2 对象中指向的 Struct1 对象的索引变量时,在某些情况下会返回错误的变量。

为什么指向向量中包含的对象的指针有时会指向向量中的不同对象?

struct Struct1
{
    size_t index;
    std::vector<size_t> data;
}

struct Struct2
{
    Struct1 *s1;
}

class MyClass
{
    std::vector<Struct1> s1s;
    std::vector<Struct2> s2s;
    size_t propIndex = 0;

    void input(QByteArray &line)
    {
        if (line == "1") {
            for (size_t i = s1s.size(); i <= propIndex; i++) {
                s1s.push_back({ .index = i, .data= {} });
            }
            QByteArrayList list = getList();
            for (auto id : list)  s1s.at(propIndex).data.push_back(id.toULongLong());
        }
        else {
            if (propIndex == s2s.size()) {
                s2s.push_back({ .s1 = nullptr });
            }

            if (line == "2") {
                size_t index = getIndex();
                for (size_t i = s1s.size(); i <= index; i++) {
                    s1s.push_back({ .index = i, .data= {} });
                }
                s2s.at(propIndex).s1 = &s1s.at(index);
            }
        }

        propIndex++;
    }

    QByteArrayList output()
    {
        QByteArrayList output;

        for (auto s2 : s2s) {
            output += QByteArray::number(s2.s1->index) + "\n";
        }

        return output;
    }
}

【问题讨论】:

标签: c++ pointers vector


【解决方案1】:

问题是你把一个指针指向一个向量中的一个项目:

s2s.at(propIndex).s1 = &s1s.at(index);

vector 是一个动态结构,它的数据在增长时可能会重新分配。所以任何push_back() 都可以使所有指针失效:

s1s.push_back({ .index = i, .data= {} });

请注意,向量分配算法旨在为需要增长的几个元素保留空间。这解释了该问题仅不时出现。

一种解决方案可能不是保留指针,而是保留元素的索引以及指向向量的指针。

【讨论】:

  • 谢谢,这就解释了。我认为您提出的解决方案会使我首先使用指针的原因无效,但无论如何我都必须找到不同的方法。
  • @xaxxon 是的,我正在考虑提出shared_ptr(因为根据设计,这些向量将在 s1s 和 s2s 之间共享)。但我认为 OP 首先需要这个向量来分配对象。
  • 那么我能做的是独立分配对象并将unique_ptrs 放在向量中吗?如果是这样,一旦其unique_ptr 被释放/销毁,这些对象就会被销毁,对吧?
  • @bur 是的,这确实是一个想法。但 unique_ptr 旨在保持唯一性。如果您的 s2s 是唯一使用它的人,您可以使用它。如果您需要相同指针的多个用户(例如在 s2s 和 s1s 中),请改为使用 shared_ptr。
  • @Christophe 仅在您想要共享所有权时使用共享ptr。否则,您需要一个唯一 ptr 向量和一个原始指针向量。在他的情况下,所有权生命周期是相同的,因此不需要共享 ptr 的额外开销。
【解决方案2】:

正如 cmets 关于接受的答案所讨论的,一个可能的解决方案是使用 unique_ptrs。

在 OP 示例代码中,Struct1 向量将替换为 unique_ptr 向量:

    std::vector<std::unique_ptr<Struct1>> s1s;

然后需要独立分配对象并创建唯一指针存储在向量中,我们需要调用.get()来获取指向对象的原始指针:

    if (line == "1") {
        for (size_t i = s1s.size(); i <= propIndex; i++) {
            s1s.push_back(std::unique_ptr<Struct1>(new Struct1({ .index = i, .data = {} })));
        }
        QByteArrayList list = getList();
        for (auto id : list)  s1s.at(propIndex)->data.push_back(id.toULongLong());
    }

...

            if (line == "2") {
            size_t index = getIndex();
            for (size_t i = s1s.size(); i <= index; i++) {
                s1s.push_back(std::unique_ptr<Struct1>(new Struct1({ .index = i, .data = {} })));
            }
            s2s.at(propIndex).s1 = s1s.at(index).get();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-19
    • 2011-10-01
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多