4

私はC++が初めてなので、ご容赦ください。

次のような構造体を作成しました。

struct node{
   double startPoint;
   double endPoint;
   vector<node*> children;

   void addChild(node *aNode){
      children.push_back(aNode);
   }
   void addPoints(double start, double end){
      startPoint = start;
      endPoint = end;
   }
};

私のプログラムの行には、次のものがあります。

vector<node*> data;
....
node *temp = (node*)malloc(sizeof(node));
temp->addPoints(lexical_cast<double>(numbers[0]), lexical_cast<double>(numbers[1]));
data[index]->addChild(temp);

ここで、"Index" はベクター データのインデックスです。これらのlexical_cast数値を文字列から double に変換しています。

行まですべてが機能しaddChild(temp)ます。

端末はこれを吐き出します:

First-chance exception at 0x585b31ea (msvcr90d.dll) in Tree.exe: 0xC0000005: Access violation reading location 0xcdcdcdc1.
Unhandled exception at 0x585b31ea (msvcr90d.dll) in Tree.exe: 0xC0000005: Access violation reading location 0xcdcdcdc1.

しかし、私はそれに対処する方法がわかりません。

4

3 に答える 3

2

mallocスペースを割り当てますが、そこには何も入れません。プレーンな古いデータ構造 (または簡単に初期化可能なクラス) に対しては問題なく動作し、C ではそれで十分です。

C++ では、std::vectorいくつかの不変条件を確立するために適切に構築する必要があるクラスがあります。これは、自動保存期間を持つオブジェクトの直接宣言で行われますが、動的に割り当てられたオブジェクトの場合は、new代わりにmalloc.

例えば、

std::vector<int> global;    // (1)
void foo() {
    std::vector<int> local; // (2)
    std::vector<int> *bad = malloc(sizeof(*bad));  // (3)
    std::vector<int> *good = new std::vector<int>; // (4)
    std::unique_ptr<std::vector<int>> better(new std::vector<int>); (5)
}
  1. 問題ありません-このグローバルは自動的に初期化されます(つまり、コンストラクターが呼び出されます)
  2. 問題ありません-このローカル変数も自動的に構築され、foo終了するとすぐに適切に破棄されます
  3. bad呼び出すメソッドは、コンストラクターが既に実行されていると想定し、実行していないため、何にも 使用できません。
    • わかりました。placement new を使用して明示的に構築しないbadと、何にも使用できません。ただし、これを行うべきではありません。カスタム割り当てで巧妙またはトリッキーなことを行っている場合にのみ適切です。
  4. これで問題ありません(ただし、手動で削除する必要があることに注意してください-fooメモリリークがあります)
  5. これは優れています - 手動でクリーンアップする必要はありません

nodeここで、クラスにもコンストラクターがあることに注意してください。この場合、それは自動的に生成され、vectorコンストラクターを呼び出すだけです。それでも、それを呼び出す必要があります。つまり、newを動的に割り当てるために使用しますnode

したがって、プログラムはおそらく次のようになります。

std::vector<std::unique_ptr<node>> data;
...
std::unique_pre<node> temp(new node);
temp->addPoints(...);
data[index]->addChild(temp);

data[index]が有効であると仮定していることに注意してください(addChildベクターを作成する方法は既に知っています)、によって実装された単一所有者モデルunique_ptrが適切です。

于 2013-08-07T20:19:03.513 に答える
1

コードを見る限り、data配列にノードを追加することはありません

data.push_back(something);

したがって、アクセスdata[index]すると、配列の割り当てられたメモリが不足します。そのブロックにメモリを設定しようとするまで(addChild要素を配列にプッシュしようとすることによってchildren)文句を言うことはありません。

于 2013-08-07T20:08:32.580 に答える