【问题标题】:Duplicate pointers after after erase from vector从向量中擦除后的重复指针
【发布时间】:2015-01-17 16:21:16
【问题描述】:

我重载了 operator-=() 以从指针向量中删除元素(指针是唯一的,因此无需删除所有出现,一旦指针被擦除,循环就可以终止):

Rooms& Rooms::operator-=(Course *c) {
    for (Iter i = rooms.begin(); i != rooms.end(); ++i) {
        if (**i == *c) {
            *i = NULL;
            i = rooms.erase(i);
            break;
        }
    }
    return *this;
}

问题是,在应用到向量之后,我得到了向量最后一个元素的重复指针。之前:

-------------------------------------------------------------------
| POL | CAE | RUS | ENG | BUS | JPY |     |     |     |     |     |
| G 1 | G 1 | G 2 | G 2 | G 2 | G 2 |     |     |     |     |     |
|   9 |   9 |  10 |  10 |  10 |  10 |     |     |     |     |     |

移除 ENG & BUS 后:

-------------------------------------------------------------------
| POL | CAE | RUS | JPY | JPY | JPY |     |     |     |     |     |
| G 1 | G 1 | G 2 | G 2 | G 2 | G 2 |     |     |     |     |     |
|   9 |   9 |  10 |  10 |  10 |  10 |     |     |     |     |     |

应该改变什么才能真正得到结果:

-------------------------------------------------------------------
| POL | CAE | RUS | JPY |     |     |     |     |     |     |     |
| G 1 | G 1 | G 2 | G 2 |     |     |     |     |     |     |     |
|   9 |   9 |  10 |  10 |     |     |     |     |     |     |     |

任何帮助将不胜感激。

编辑:

我的打印功能是这样的:

std::ostream& operator<<(std::ostream& out, const Rooms& rs) {
    std::vector<std::string> output(3);
    std::ostringstream temp;
    for (int i = 0; i < rs.rooms.capacity(); ++i) {
        if (rs.rooms[i]) {
            temp << "| " << rs.rooms[i]->getCode() << " ";
            output[0] += temp.str();
            temp.str("");
            temp << "| G" << std::setw(CODE_LENGTH - 1)
                 << rs.rooms[i]->getGroup() << " ";
            output[1] += temp.str();
            temp.str("");
            temp << "| " << std::setw(CODE_LENGTH)
                 << rs.rooms[i]->getSize() << " ";
            output[2] += temp.str();
            temp.str("");
        } else {
            output[0] += "|     ";
            output[1] += "|     ";
            output[2] += "|     ";
        }
    }
    output[0] += "|";
    output[1] += "|";
    output[2] += "|";
    out <<  printHorizont(rs.size) << output[0] << std::endl
        << output[1] << std::endl << output[2] << std::endl;
    return out;
}

看起来很复杂,但找不到更好的打印方式。

【问题讨论】:

  • 为什么这样:i = rooms.erase(i); ?
  • @Haketo 被擦除的迭代器失效。 erase 将一个有效的迭代器返回到曾经位于被擦除元素后面的元素。 OP:如果两个可擦除元素直接出现在彼此之后,此代码将跳过元素,但它应该缩短向量。在这一切之后使用向量的代码是否有可能不检查更改的长度?
  • @Haketo 否则我在打印结果时遇到分段错误。在打印功能中,我使用 rooms[i] 来访问元素。
  • 请说明你是如何调用函数的?你怎么知道你得到了重复的条目?
  • @AndrzejSmyk - 问题是您应该使用诸如find_ifremove_if 等算法函数,而不是像这样的循环。那么你的错误一般不会发生。

标签: c++ vector


【解决方案1】:

operator&lt;&lt;()

for (int i = 0; i < rs.rooms.capacity(); ++i) {

对于rs.rooms.size() &lt;= i &lt; rs.rooms.capacity(),基本上rs.rooms[i]是非法的。

使用迭代器遍历向量,你永远不会犯这样的错误。如果你真的需要打印那些“空格”,你可以写成

for (int i = 0; i < rs.rooms.capacity(); ++i) {
    if (i < rs.rooms.size() && rs.rooms[i]) {
        // access rs.rooms[i]
    } else {
        // print empty placeholder
    }
}

【讨论】:

  • 这表示错误出在您的打印例程中,而不是您的 operator -= 代码中,在您的打印例程中将 capacity() 更改为 size()。
  • 感谢您发布此信息,我有一个问题。由于我也需要打印空格,所以迭代器会在最后一个非空项之后还是在容量给出的最后一个元素之后结束?
  • 迭代器在最后一个逻辑非空项之后结束。
  • 所以如果使用迭代器,我将无法打印空槽。
  • @AndrzejSmyk 我为您更新了答案,以避免在打印出您想要的内容时访问非法地址。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-29
  • 1970-01-01
  • 1970-01-01
  • 2019-05-05
相关资源
最近更新 更多