You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么我无法对std::set中Vertex对象的vector成员调用push_back?

核心问题解答

std::set的迭代器属于常量迭代器范畴,->运算符返回的是const T*类型的指针,指向的是常量对象,你无法通过该指针修改对象的成员。
原因是std::set是有序关联容器,容器的排序逻辑依赖元素本身的值,一旦允许随意修改元素内容,会直接破坏容器内部的有序结构,引发未定义行为,因此C++标准强制要求std::set迭代器返回只读的常量对象。


代码执行失败的两个直接原因

  1. 迭代器有效性判断顺序错误
    你先对it1解引用构造p1,再判断it1 != vertices_.end(),如果传入的c1不在顶点集合中,it1就是end()迭代器,解引用空迭代器直接触发崩溃。
  2. 尝试修改set的常量元素
    即使it1是有效迭代器,你通过it1->neighbors访问到的是const std::vector<...>,调用push_back修改常量对象的成员,属于编译期就不允许的操作,如果你的代码是运行期崩溃大概率是第一个问题,要是编译失败就是第二个问题。

另外你当前的边插入逻辑也存在问题:你构造的p1是当前顶点和权重的pair,相当于把自己加入自己的邻接表,正常应该是把*it2(对端顶点)加入it1的邻接表。


修复方案

方案1:用mutable修饰不参与排序的成员

因为你的Vertex类的排序、判等逻辑只用到ID_字段,neighbors的修改完全不影响容器的有序性,你可以给neighbors加mutable修饰,允许在常量对象上修改该成员:

mutable std::vector<std::pair<Vertex, int>> neighbors;

方案2:替换容器为std::map(更推荐)

你可以把顶点集合改成std::map<char, Vertex>,键是顶点ID,值是顶点对象,map的有序性只由键保证,值可以随意修改,不需要额外改Vertex类的定义:

// 修改Graph类的成员定义
protected:
    std::map<char, Vertex> vertices_;

// 对应的insertEdge逻辑调整
void Graph::insertEdge(char c1, char c2, int w) {
    auto it1 = vertices_.find(c1);
    auto it2 = vertices_.find(c2);
    // 先判断两个顶点都存在
    if(it1 != vertices_.end() && it2 != vertices_.end()) {
        it1->second.neighbors.emplace_back(it2->second, w);
        // 如果是无向图还要加反向边:it2->second.neighbors.emplace_back(it1->second, w);
    }
}

内容的提问来源于stack exchange,提问作者Jib Ran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 18:27:04