【问题标题】:Why am I unable to use push_back on this vector?为什么我不能在这个向量上使用 push_back?
【发布时间】:2021-08-21 22:26:32
【问题描述】:

我正在尝试创建图表。我将边建模为连接顶点的std::pair 以及连接这些顶点的边的权重。我通过另一个图形类插入这条边,该图形类将所有这些顶点保存为std::set

我的做法如下:

这是顶点类:

class Vertex {
public:
    friend std::ostream &operator<<(std::ostream &os, const Vertex &v);
    Vertex(char c) : ID_(c) {}
    bool operator==(const Vertex &rhs) const {
        return (this->ID_ == rhs.ID_);
    }
    bool operator<(const Vertex &rhs) const {
        return (this->ID_ < rhs.ID_);
    }

    char ID_;
    std::vector<std::pair<Vertex, int>> neighbors;
};

这是包含顶点的图类:

class Graph {
public:
    friend std::ostream &operator<<(std::ostream &os, const Graph &g);
    Graph(); 
    Graph(char c[]);
    void insertVertex(char c);
    void insertEdge(char ID1, char ID2, int weight);

protected:
    std::set<Vertex> vertices_;
};

这是我的边缘插入方法:

void Graph::insertEdge(char c1, char c2, int w) {
    auto it1 = vertices_.find(c1);
    auto it2 = vertices_.find(c2);
    auto p1 = std::make_pair(*it1, w);

    if(it1 != vertices_.end())
        it1->neighbors.push_back(p1);  // Fails here
} 

-&gt; 运算符是返回迭代器指向的对象,还是返回类似 const 引用的对象?

【问题讨论】:

  • @JeJo 有一个构造函数可以将 char 转换为顶点,所以没问题。
  • “失败”是什么意思?
  • 我的错,在那里我尝试访问迭代器指向的对象的属性时编译失败。
  • 您应该在问题中包含编译错误消息。
  • 请注意,insertEdge() 没有使用 c2/it2 来做任何有意义的事情,如果 c1 不存在于集合中,std::make_pair(*it1, w) 是未定义的行为(it1end 迭代器)。在这段代码中根本没有理由使用*it1,请根据需要使用c1c2

标签: c++ vector std-pair


【解决方案1】:

我想我找到了问题所在。 std::set 不能修改,至少不能直接修改。为了使其元素可修改,我做了这样的事情:

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

基本上将我要修改的元素的属性设置在集合中可变

感谢这个答案: https://stackoverflow.com/a/7340470/14635766

【讨论】:

  • 编译错误是有原因的,使用mutable 绕过它是一件危险的事情。 set 阻止您修改元素是因为如果您修改它们,set 将不知道这一点并且无法更新其内部簿记(例如 it1-&gt;ID_ = ...)。您似乎实际上想要mapunordered_map,而不是set,因为这将允许您修改值。如果必须使用set,则应将extract节点修改,然后发回set;这样它就知道变化了。
  • 非常感谢!虽然,由于我对这个数据结构相当陌生,但是使集合不可修改的想法/应用程序是什么?我使用 set 的原因是使用任何可以防止重复元素进入的数据结构。但我不想使用 map 的原因是我不知道应该分配哪些键。
  • 而在这种情况下,当我使邻居的 std::map (集合中对象的属性)可变时,是否也意味着 std::map 所持有的元素也是可变的?在这种情况下,从 std::set 转移到 std::map 并找出密钥是值得的。
  • 使集合不可修改的想法是什么? set 中的元素是隐式排序的(通常通过存储在某种树中)。如果您可以更改它们,那么每次您这样做时都必须重建setstd::map 持有的元素是可变的吗? 值是,键(原因与 set 中的元素相同)不是。
  • 我个人不会依赖它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-03
  • 1970-01-01
  • 2021-11-06
相关资源
最近更新 更多