C ++数据结构分配器问题

时间:2014-06-24 13:35:54

标签: c++ data-structures allocator

我在使用C ++实现我的图表时遇到了麻烦。

目前,我刚刚实现了Vertex和Edges,这里是类:

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 Vertex& param);
    Vertex& operator=(const Vertex& param);
    Vertex(Vertex&& param);
    Vertex& operator=(Vertex&& param);
    ~Vertex();
    bool operator!=(const Vertex& param);
    bool operator==(const Vertex& param);
    bool operator<(const Vertex& 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::ostream& operator<<(std::ostream& out, const Vertex& 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 Vertex& param):
    id(param.id), soglia(param.soglia), degree(param.degree), peso(param.degree), visited(param.visited){
}

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

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

Vertex& Vertex::operator=(Vertex&& 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 Vertex& param){
    return !(this->id==param.id);
}

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

bool Vertex::operator<(const Vertex& 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::ostream& operator<<(std::ostream& out, const Vertex& 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 Edge& param);
    Edge& operator=(const Edge& param);
    Edge(Edge&& param);
    Edge& operator=(Edge&& param);
    ~Edge();

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

    friend std::ostream& operator<<(std::ostream& out, const Edge& a);
};

} /* namespace MarcoGraphs */

#endif /* EDGE_H_ */

Edge.cpp

#include "Edge.h"

namespace MarcoGraphs {

Edge::Edge(Vertex v1, Vertex v2):
    v1(&v1), v2(&v2){
}

Edge::~Edge() {
}

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

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

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

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

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


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

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

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


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

std::ostream& operator<<(std::ostream& out, const Edge& 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*, _Args&& ...) [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>&) [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_type&) [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::Vertex&&)
  Vertex(Vertex&& param);
  ^
../Vertex.h:27:2: note:   candidate expects 1 argument, 0 provided
../Vertex.h:25:2: note: MarcoGraphs::Vertex::Vertex(const MarcoGraphs::Vertex&)
  Vertex(const Vertex& 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

你能帮助我吗?谢谢:)

2 个答案:

答案 0 :(得分:0)

std::vector<MarcoGraphs::Vertex> v(10);这会创建一个包含10个元素的向量,但为此它需要一个默认的构造函数,而这个元素是你没有的。

您可以使用reserve来获得足够大的向量,或者将Vertex传递给向量的构造函数。

在这里,有一些参考:

答案 1 :(得分:0)

Zsolt的回答是正确的,但也许并不能完全回答你的问题。所以我会尝试扩展它。

在C ++中,“默认构造函数”是一个不带参数的构造函数。在Vertex,Vertex()的情况下。

当您创建一个类并且没有定义任何构造函数时,C ++会为您创建一个默认构造函数,这可能就是您尚未遇到此问题的原因。对于Vertex,您已经创建了一些构造函数,因此编译器认为您已明确省略了默认构造函数。这通常是可取的,因为通常不存在有意义的默认值。

当您拨打电话时:

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

您告诉编译器要构建10个顶点的向量。由于您尚未提供分配器作为模板参数,因此它使用默认分配器,该分配器调用默认构造函数,该构造函数不存在。这就是您所看到的错误告诉您的内容(现在再次阅读它们,您应该能够理解它们的输出)。

在主循环中,您使用push_back将Vertexes添加到向量中,因此实际上不需要构造10个默认顶点。您有几种选择:

  1. 从v的定义中删除“(10)”,让编译器为您分配内存(在本例中为首选)。
  2. 创建一个有意义的默认构造函数(在这种情况下可能是错误的)。
  3. 遵循Zsolt的建议并保留记忆。
  4. 保留内存实际上是一种优化,当您知道向量将存储多少个对象并且不希望使用push_back命令动态重新分配内存时,这非常有用。对于你的具体程序,我认为这是一个不成熟的优化,只会删除“(10)”。