5

私はここでいくつかの困難な状況にあり、私はいくつかの体が私を助けてくれることを願っています。

私は次のものを持っています、

struct CandyBar{ 
  std::string name; 
  double weight; 
  int calories; 
} ;

さて、多くのCandyBarを含む構造の配列を作成することは、私が行ったように非常に簡単です。

int main(){
   CandyBar bars[] = {{"Mango tart", 2.3, 100}, {"Yo Yo", 3.2, 130}, {"Orange Ball", 1.7, 98}};
  return 0;
}

しかし、今はnewを使用して同じ構造を作成したいと思います。私が思うと非常に単純ですが、これはクラッシュして機能しません。

CandyBar *bars = new CandyBar;
  (*bars).name = "Mango tart";
   bars->weight =  2.3;
   bars->calories =  100;
   bars += 1;

  (*bars).name = "Yo Yo";
  bars->weight =  3.2;
  bars->calories =  130;

  bars += 1;
  (*bars).name =  "Orange Ball";
  bars->weight =  1.7;
  bars->calories =  98; 

しかし、これは機能しません。最初のポインタは最初の構造を指すメモリ位置だと思うので、構造を作成してから、バー+ = 1を使用してアドレスを増やし、ポインタの作成を続けますが、本当に深刻なものがありません。

よろしくお願いします。

4

4 に答える 4

15

2番目の例では、単一のCandyBar構造体のみを割り当てていますが、それを配列であるかのように扱っています。それはうまく終わらないでしょう、そしてそれはバッファオーバーフローのレシピです。

の配列を割り当てるには、次のように、配列がCandyBars必要であることをnewに通知する必要があります。

CandyBar* bars = new CandyBar[3];

CandyBarsの配列を削除するときは、次のように配列削除を使用していることを確認してください。

delete[] bars;

とはいえ、C ++プロダクションコードでは、この特定の場合に必要なほど多くのリソース管理を処理する必要がないため、通常はstd::vectorまたはstd::arrrayを使用してこの状況を処理します。

ヒープに配列を動的に割り当て、それでもRAIIを使用する必要がある場合はboost::shared_arrayboost::scoped_array.

于 2013-01-01T22:10:32.523 に答える
6

Space is only being allocated for one CandyBar, so you are writing to unallocated heap memory. This is a big no-no. You are actually lucky that it is failing because this has the capability of produce very difficult to debug problems.

You can allocate room for more CandyBars like so:

CandyBar *bars = new CandyBar[3]; // 3 CandyBars.

...and don't forget to use an array deletor like so:

delete[] bars;

But still, there is the capability to overrun the number of CandyBars that you have allocated. The much preferred method of doing this in C++ is to use a std::vector.

In this example, I give CandyBar a constructor for shorthand and place them into a std::vector.

#include <string>
#include <vector>

struct CandyBar{ 
  std::string name;
  double weight;
  int calories;
  CandyBar(std::string name, double weight, int calories)
  {
      this->name = name;
      this->weight = weight;
      this->calories = calories;
  }
};

int main()
{
    std::vector<CandyBar> bars;
    bars.push_back(CandyBar("Mango tart", 2.3, 100));
    bars.push_back(CandyBar("Yo Yo", 3.2, 130));
    bars.push_back(CandyBar("Orange Ball", 1.7, 98));

    return 0;
}

No new's, no delete's, no leaks, no corruption.

I would also add that if you are using a compiler with some C++11 support and do not want the dynamic allocation that std::vector gives you, you may consider using std::array instead.

于 2013-01-01T22:25:08.690 に答える
1

Foo * a = new Fooの1つのインスタンスにスペースを割り当てますFoo。の配列を割り当てる場合はFoo、を使用する必要がありますFoo * a = new Foo[ARRAY_LEN]


基本的に、本当にやりたいことは、オブジェクトの配列(この場合はオブジェクト)を保持するためにメモリを動的に割り当てることCandyBarです。問題は、newそのようなオブジェクトの1つにのみメモリを割り当てる演算子を使用していることです。次に、返されたメモリアドレスを、配列を指しているかのように使用しようとしています。必然的に、まだ割り当てていないメモリにアクセスしようとします。これにより、セグメンテーション違反が発生します(せいぜい)。

本当に探している演算子は、指定された数のオブジェクトの配列に十分なメモリを割り当てるnew[]演算子(として呼び出されます)です。new CandyBar[ARRAY_LEN]次に、返されたメモリアドレスを取得して、メモリ割り当てをオーバーランすることを恐れずに、指定したサイズの配列とまったく同じように扱うことができます。

一般に、プログラムの存続期間中に拡大または縮小する可能性のあるsのコレクションを扱っている場合CandyBar、固定サイズの配列を割り当てることはできません。std::vectorC ++ STLのテンプレートクラスを見てください。aは、格納するsのstd::vector<CandyBar>数に応じて動的に拡大または縮小できCandyBar、配列であるかのように自由にアクセスできます(例:)foo[42]

于 2013-01-01T22:09:41.590 に答える
0

次の配列を割り当てる必要がありますCandyBar

CandyBar *bars = new CandyBar[20];

次に、、...などを使用bars[0]bars[1]bars[19]、個々のキャンディーバーにアクセスします。

コードによってポインターにbars + 11が追加sizeof CandyBarされますが、これは未割り当ての領域を指していることに注意してください(単一のCandyBarを割り当てたばかりであるため)。したがって、コードがクラッシュします。

于 2013-01-01T22:09:49.433 に答える