1

隣接リストでの作業->有向加重グラフ

1つのクラスは次のようになります。つまりヘッダー:

class CGraph;
class CMap {
public:
    //voided constructors and destructors
    //functions one is:
    void SetDirGraph(string commands);

private:
   CGraph* m_myMap;
};

2番目のクラス:

class CNode {
public:
    //voided constructor and desctructor
    int m_distance, m_vert;
    bool m_isKnown;
};

typedef struct edges {
    int v2, weight;
} edge;

class CGraph {
public:
    CGraph(int map_size);
    ~CGraph(void);

    void AddMap(int v1, int v2, int weight);
    void AddEndVert(int v2, int weight);

private:
    list<edge> List;
    int size;

public:
    CNode* verts;
};

ファイルから頂点を読み取っていますが、それは機能します。私の問題は、与えられたコードに基づいて隣接リストを作成するのに問題があることです。リストを指すポインタを最初に使用しようとしていますが、正しく機能していません。リストへのポインタを上書きせずに作成する方法がわかりません。

void CMap::SetDirGraph(string command) {
    istringstream buffer(command)
    char ch;
    int num, vert1, vert2, weight; //specify vertices and weight and number of vertices

    buffer>>ch;  //throw away first character (not needed)
    buffer>>num // size of vertices

    while(!buffer.eof()) {   // keep reading until end of line
        buffer>>v1;           // vertex  start
        buffer>>v2;          // vertex end
        buffer>>weight;

        m_myMap = new CGraph(map_size);  //initialize m_myMap.
        m_myMap->verts->m_vert = v1;  // mymap->verts->vert points to first edge
        m_myMap->AddMap(v1, v2, weight);  // create list?
        m_myMap->AddEndVert(v2, weight);  //create list? push v2 and weight on my list using my list.
    }
}

私はいくつかの異なる方法を試しましたが、私は自分自身を混乱させ続けています。正しい方向のどのポイントも素晴らしいでしょう。

編集:作成する必要がある場合は、主要なものを公開するだけで、さらに多くのコードがあります。「機能しない」とは、前の頂点を上書きしているだけのことです。m_myMapを使用して配列を作成する必要があるかどうかわかりません(試しても上書きしてメモリエラーが発生します)。コンパイラエラーはありません。

4

1 に答える 1

1

リストへのポインタを上書きせずに作成する方法がわかりません。

アプリケーションとは別に、この質問への答えはnew演算子です。これは、サンプルコード内で使用したため、知っていると思います。int * a = new int(42);ヒープ上のメモリを割り当てるようなコードintは、不要になったときにクリーンアップする責任があります。これにより、変数が使用可能になる期間を完全に制御できます。一方int x = 42; int * a = &x;xは、スコープがなくなると自動的にクリーンアップされ、a意味のあるデータがなくなったメモリブロックへのポインタになります。逆参照しようとすると、未定義の動作が発生し、運が良ければプログラムが爆発します。

C ++ 11標準、またはスマートポインターを提供するライブラリを使用できる場合は、可能な限り、ポインターを自分で管理するよりも、それらを優先する必要があります。スマートポインタは、割り当てられたメモリを保持し、破壊されたときに自動的に解放するオブジェクトです。より具体的な情報は、使用しているスマートポインターの種類によって大きく異なります。スマートポインタを使用する理由は、自分で管理を行うのは面倒でエラーが発生しやすいためです。割り当てたポインタを使用しない場合delete、アプリケーションは、いつか爆発するまで、より多くのメモリを割り当て続けます(割り当てるメモリの頻度と量によって異なります)。これはリークと呼ばれます。delete2回以上電話をかけると、プログラムもベイルアウトします。アプリケーションのC++11の例を次に示しshared_ptrます。

class CMap
{
  private:
    std::shared_ptr<CGraph> m_myMap;
  // etc.
};

// in SetDirGraph
m_myMap.reset(          // if the smart pointer has previously been managing
                        // memory, it will free it before allocating new
  new CGraph(map_size)  // allocate CGraph as before
);

それに加えて、うまくいけばあなたの質問に答えるものがありますが、私はあなたのコードに関していくつかの潜在的な問題に遭遇しました:

  • 間違いなく間違っているSetDirGraphあなたが設定しm_myMap->verts->m_vert = v1た。m_myMap->vertsポインタです。新しく作成m_myMapしたためverts、初期化されていないため、ランダムなメモリブロックを指しています。次に、によってそれを逆参照しようとしm_myMap->verts->m_vert = v1ます。これは機能しません。最初に作成する必要があります。vertsつまり、verts = new CNode;

  • typedef struct edges { /* etc */ } edge;typedefはC構造であり、C++のラッパーは必要ありません。それはすべて機能しますが、それは本当に冗長であり、それらの構成要素の多くは、作業している名前空間を汚染するだけです。

  • そもそも本当にポインタが必要ですか?提供されたスニペットは、それらを使用する必要がある理由を示唆していません。ポインターの使用を最小限に抑えたいと思うでしょう(または少なくともスマートポインターを使用してください。上記を参照してください)

于 2012-06-08T06:30:00.623 に答える