1

After a 2 years break, I've started using C++ again, and I'm pretty rusty. I'm trying to implement a 5-coloring algorithm for a graph, but I'm having trouble with vectors.

I've 3 classes (snippets below). The problem is that somewhere in Graph::Graph(), a copy constructor is called on both vectors (While troubleshooting the Graph::solve() function, I found that the vertices in Edge::_from/Edge::_to are not references to the vertices inside Graph::_vertices, when I change the color of one vertex inside Graph::_vertices, vertices inside Edge::_to/Edge::_from aren't affected).

I've used this code to test

    Vertex v1 = Vertex("A");
    Vertex v2 = Vertex("B");
    std::vector<Vertex> vertices = { v1, v2 };

    v1.color() = 1;

    Edge e1_2 = Edge(v1, v2);
    std::vector<Edge> edges;

    std::cout << v1 << std::endl; //output A(1)
    std::cout << e1_2 << std::endl; //output A(1) -> B(-1) so v1 is a reference

    Graph g = Graph(edges, vertices);

    std::cout << v1 << std::endl; //output A(1)
    std::cout << e1_2 << std::endl; //output A(1) -> B(-1)
    std::cout << g.vertices().at(0) << std::endl; //output A(-1) WHY is it -1 and not 1 ?

    v1.color() = 2;
    std::cout << v1 << std::endl; //output A(2)
    std::cout << e1_2 << std::endl; //output A(2) -> B(-1)
    std::cout << g.vertices().at(0) << std::endl; //output A(-1)

I know it is the initilization list inside Graph::Graph() that call the copy constructor on both vectors, but I can't get rid of it because it won't compile without it, as the vectors must be initialized. But I don't get why Vertex::_identifier are copied, but Vertex::_color are set to the default value.

I also used an initilization list in Edge::Edge(), but it didn't call the copy constructor on the vertices, as they are real references.

Is there a ""clean"" way to resolve this (without pointers if possible) ?

Vertex

class Vertex {
    private:
        std::string _identifier;
        int _color; //-1 = no color
    public:
        explicit Vertex(std::string identifier) : _identifier(identifier), _color(-1) {}
    ...
}

Edge

class Edge {

    private:
        Vertex& _from;
        Vertex& _to;

    public:
        Edge(Vertex& from, Vertex& to) : _from(from), _to(to) {}

        Vertex from() const;
        Vertex to() const;
    ...
}

Graph

class Graph {
    private:

        std::vector<Vertex> _vertices;
        std::vector<Edge> _edges;
    public:
        Graph(std::vector<Edge>& edges, std::vector<Vertex>& vertices) : _edges(edges), _vertices(vertices) {}
    ...
}
Ladislus
  • 73
  • 8

1 Answers1

1

Pass std::vector to constructor without copy

Move instead of copy:

Graph(std::vector<Edge> edges, std::vector<Vertex> vertices)
    : _edges(std::move(edges)), _vertices(std::move(vertices))

// example usage
Graph g(std::move(edges), std::move(vertices));

However, avoiding copying of the vector is not sufficient for you. You also copy vertices into the vector itself. You could instead create the edges between the copies in the vector rather than the variables they were copied from:

Edge e1_2 = Edge(vertices[0], vertices[1]);

Furthermore: Don't use reference members. Use pointers or reference wrappers.

eerorika
  • 232,697
  • 12
  • 197
  • 326