Проблемы с распределителем структур данных C

#c #data-structures #allocator

#c #структуры данных #распределитель

Вопрос:

У меня возникли проблемы с реализацией моего графика на C .

На данный момент я только что реализовал вершины и ребра, вот классы:

Vertex.h

 #ifndef VERTEX_H_
#define VERTEX_H_
#include <string>
#include <iostream>

namespace MarcoGraphs {

enum class Colors {black, red};

class Vertex {
private:
    std::string id;
    int soglia, degree;
    double peso;
    Colors visited;
public:
    Vertex(std::string id);
    Vertex(const Vertexamp; param);
    Vertexamp; operator=(const Vertexamp; param);
    Vertex(Vertexamp;amp; param);
    Vertexamp; operator=(Vertexamp;amp; param);
    ~Vertex();
    bool operator!=(const Vertexamp; param);
    bool operator==(const Vertexamp; param);
    bool operator<(const Vertexamp; param);
    std::string getId();
    void setDegree(int degree);
    int getDegree();
    void incrementDegree();
    void setSoglia(int soglia);
    int getSoglia();
    void setVisited(Colors mycolors);
    Colors getVisited();
    void setPeso(double peso);
    double getPeso();
    friend std::ostreamamp; operator<<(std::ostreamamp; out, const Vertexamp; a);
};

} /* namespace MarcoGraphs */

#endif /* VERTEX_H_ */
  

Vertex.cpp

 #include "Vertex.h"

namespace MarcoGraphs {

Vertex::Vertex(std::string Id):
    id(Id), soglia(0), degree(0), peso(0), visited(Colors::black){
}

Vertex::~Vertex() {
}

Vertex::Vertex(const Vertexamp; param):
    id(param.id), soglia(param.soglia), degree(param.degree), peso(param.degree), visited(param.visited){
}

Vertexamp; Vertex::operator=(const Vertexamp; param){
    id = param.id;
    soglia = param.soglia;
    degree = param.degree;
    peso = param.peso;
    visited = param.visited;
    return *this;
}

Vertex::Vertex(Vertexamp;amp; param):
        id(param.id), soglia(param.soglia), degree(param.degree), peso(param.degree), visited(param.visited){
    param.id.clear();
}

Vertexamp; Vertex::operator=(Vertexamp;amp; param){
    id = param.id;
    param.id.clear();
    soglia = param.soglia;
    degree = param.degree;
    peso = param.peso;
    visited = param.visited;
    return *this;
}

bool Vertex::operator!=(const Vertexamp; param){
    return !(this->id==param.id);
}

bool Vertex::operator==(const Vertexamp; param){
    return this->id==param.id;
}

bool Vertex::operator<(const Vertexamp; param){
    return this->id<param.id;
}

std::string Vertex::getId(){
    return id;
}

void Vertex::setDegree(int degree){
    this->degree = degree;
}

int Vertex::getDegree(){
    return degree;
}

void Vertex::incrementDegree(){
    degree  =1;
}

void Vertex::setSoglia(int soglia){
    this->soglia = soglia;
}

int Vertex::getSoglia(){
    return soglia;
}

void Vertex::setVisited(Colors mycolor){
    this->visited = mycolor;
}

Colors Vertex::getVisited(){
    return visited;
}

void Vertex::setPeso(double peso){
    this->peso = peso;
}

double Vertex::getPeso(){
    return peso;
}

std::ostreamamp; operator<<(std::ostreamamp; out, const Vertexamp; a){
    out << a.id << " " << a.peso << " " << a.soglia << "n";
    return out;
}

} /* namespace MarcoGraphs */
  

Edge.h

 #ifndef EDGE_H_
#define EDGE_H_
#include <iostream>
#include "Vertex.h"

namespace MarcoGraphs {

class Edge {
private:
    Vertex* v1;
    Vertex* v2;
public:
    Edge(Vertex v1, Vertex v2);
    Edge(const Edgeamp; param);
    Edgeamp; operator=(const Edgeamp; param);
    Edge(Edgeamp;amp; param);
    Edgeamp; operator=(Edgeamp;amp; param);
    ~Edge();

    bool operator!=(const Edgeamp; param);
    bool operator==(const Edgeamp; param);
    bool operator<(const Edgeamp; param);
    Vertex* getV1();
    Vertex* getV2();

    friend std::ostreamamp; operator<<(std::ostreamamp; out, const Edgeamp; a);
};

} /* namespace MarcoGraphs */

#endif /* EDGE_H_ */
  

Edge.cpp

 #include "Edge.h"

namespace MarcoGraphs {

Edge::Edge(Vertex v1, Vertex v2):
    v1(amp;v1), v2(amp;v2){
}

Edge::~Edge() {
}

Edge::Edge(const Edgeamp; param):
    v1(param.v1), v2(param.v2){
}

Edgeamp; Edge::operator=(const Edgeamp; param){
    v1 = param.v1;
    v2 = param.v2;
    return *this;
}

Edge::Edge(Edgeamp;amp; param):
    v1(param.v1), v2(param.v2){
    param.v1 = nullptr;
    param.v2 = nullptr;
}

Edgeamp; Edge::operator=(Edgeamp;amp; param){
    v1 = param.v1;
    v2 = param.v2;
    param.v1 = nullptr;
    param.v2 = nullptr;
    return *this;
}

bool Edge::operator!=(const Edgeamp; param){
    return !(*v1 == *(param.v1) amp;amp; *v2 == *(param.v2));
}


bool Edge::operator==(const Edgeamp; param){
    return (*v1 == *(param.v1) amp;amp; *v2 == *(param.v2));
}

bool Edge::operator<(const Edgeamp; param){
    if(*v1 != *(param.v1))
        return *v1 < *(param.v1);
    return *v2 < *(param.v2);
}

Vertex* Edge::getV1(){
    return v1;
}


Vertex* Edge::getV2(){
    return v2;
}

std::ostreamamp; operator<<(std::ostreamamp; out, const Edgeamp; a){
    out << a.v1->getId() << "," << a.v2->getId();
    return out;
}

} /* namespace MarcoGraphs */
  

Я попытался протестировать эти классы на этом небольшом примере:

main.cpp

 #include "Vertex.h"
#include "Edge.h"
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>

int main(){
    MarcoGraphs::Vertex v1("Marco");
    MarcoGraphs::Vertex v2("Stefano");
    MarcoGraphs::Vertex v3("Giovanni");


    std::vector<MarcoGraphs::Vertex> v(10);
    v.push_back(v1);
    v.push_back(v2);
    v.push_back(v3);
    return 0;
}
  

Но g выдает мне следующие ошибки:

 15:15:20 **** Incremental Build of configuration Debug for project Thesis ****
make all 
Building file: ../Main.cpp
Invoking: Cross G   Compiler
g   -O0 -g3 -Wall -c -fmessage-length=0 -std=c  11 -MMD -MP -MF"Main.d" -MT"Main.d" -o "Main.o" "../Main.cpp"
In file included from /usr/include/c  /4.9.0/bits/stl_tempbuf.h:60:0,
                 from /usr/include/c  /4.9.0/bits/stl_algo.h:62,
                 from /usr/include/c  /4.9.0/algorithm:62,
                 from ../Main.cpp:12:
/usr/include/c  /4.9.0/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Argsamp;amp; ...) [with _T1 = MarcoGraphs::Vertex; _Args = {}]’:
/usr/include/c  /4.9.0/bits/stl_uninitialized.h:515:43:   required from ‘static void std::__uninitialized_default_n_1<_TrivialValueType>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = MarcoGraphs::Vertex*; _Size = unsigned int; bool _TrivialValueType = false]’
/usr/include/c  /4.9.0/bits/stl_uninitialized.h:570:33:   required from ‘void std::__uninitialized_default_n(_ForwardIterator, _Size) [with _ForwardIterator = MarcoGraphs::Vertex*; _Size = unsigned int]’
/usr/include/c  /4.9.0/bits/stl_uninitialized.h:631:50:   required from ‘void std::__uninitialized_default_n_a(_ForwardIterator, _Size, std::allocator<_Tp>amp;) [with _ForwardIterator = MarcoGraphs::Vertex*; _Size = unsigned int; _Tp = MarcoGraphs::Vertex]’
/usr/include/c  /4.9.0/bits/stl_vector.h:1311:28:   required from ‘void std::vector<_Tp, _Alloc>::_M_default_initialize(std::vector<_Tp, _Alloc>::size_type) [with _Tp = MarcoGraphs::Vertex; _Alloc = std::allocator<MarcoGraphs::Vertex>; std::vector<_Tp, _Alloc>::size_type = unsigned int]’
/usr/include/c  /4.9.0/bits/stl_vector.h:279:34:   required from ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_typeamp;) [with _Tp = MarcoGraphs::Vertex; _Alloc = std::allocator<MarcoGraphs::Vertex>; std::vector<_Tp, _Alloc>::size_type = unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<MarcoGraphs::Vertex>]’
../Main.cpp:21:39:   required from here
/usr/include/c  /4.9.0/bits/stl_construct.h:75:7: error: no matching function for call to ‘MarcoGraphs::Vertex::Vertex()’
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^
/usr/include/c  /4.9.0/bits/stl_construct.h:75:7: note: candidates are:
In file included from ../Main.cpp:8:0:
../Vertex.h:27:2: note: MarcoGraphs::Vertex::Vertex(MarcoGraphs::Vertexamp;amp;)
  Vertex(Vertexamp;amp; param);
  ^
../Vertex.h:27:2: note:   candidate expects 1 argument, 0 provided
../Vertex.h:25:2: note: MarcoGraphs::Vertex::Vertex(const MarcoGraphs::Vertexamp;)
  Vertex(const Vertexamp; param);
  ^
../Vertex.h:25:2: note:   candidate expects 1 argument, 0 provided
../Vertex.h:24:2: note: MarcoGraphs::Vertex::Vertex(std::string)
  Vertex(std::string id);
  ^
../Vertex.h:24:2: note:   candidate expects 1 argument, 0 provided
subdir.mk:24: recipe for target 'Main.o' failed
make: *** [Main.o] Error 1
  

Можете ли вы мне помочь?Спасибо 🙂

Ответ №1:

Ответ Жолта правильный, но, возможно, не полностью отвечает на ваш вопрос. Поэтому я постараюсь подробнее остановиться на этом.

В C «конструктор по умолчанию» — это конструктор, который вызывается без аргументов. В случае Vertex, Vertex() .

Когда вы создаете класс и не определяете никаких конструкторов, C создает для вас конструктор по умолчанию, что может быть причиной того, что вы еще не столкнулись с этой проблемой. В случае Vertex вы создали несколько конструкторов, поэтому компилятор считает, что вы явно не указали конструктор по умолчанию. Это часто желательно, поскольку часто не существует значимого значения по умолчанию.

При вызове строки:

 std::vector<MarcoGraphs::Vertex> v(10);
  

Вы сообщаете компилятору, что хотите построить вектор из 10 вершин. Поскольку вы не предоставили распределитель в качестве аргумента шаблона, он использует распределитель по умолчанию, который вызывает конструктор по умолчанию, который не существует. Об этом говорят ошибки, которые вы видите (прочитайте их еще раз, и вы должны быть в состоянии понять их вывод).

В вашем основном цикле вы используете push_back для добавления вершин к вашему вектору, поэтому на самом деле нет необходимости создавать 10 вершин по умолчанию. У вас есть несколько вариантов:

  1. Удалите «(10)» из вашего определения v и позвольте компилятору выделить для вас память (предпочтительно в данном случае).
  2. Создайте эффективный конструктор по умолчанию (возможно, в данном случае неверный).
  3. Следуйте совету Жолта и зарезервируйте память.

Резервирование памяти — это действительно оптимизация, которая полезна, когда вы знаете, сколько объектов будет хранить вектор, и не хотите перераспределять память «на лету» с помощью команды push_back . Для вашей конкретной программы я бы счел это преждевременной оптимизацией и просто удалил «(10)».

Ответ №2:

std::vector<MarcoGraphs::Vertex> v(10); Это создает вектор с 10 элементами, но для этого ему нужен конструктор по умолчанию, которого у вас нет.

Вы можете либо использовать reserve , чтобы иметь достаточно большой вектор, либо передать a Vertex конструктору вектора.

Здесь есть некоторые ссылки: