2

C ++の配列でnewとdeleteをオーバーロードするためのプログラムを書いています。コードは次のとおりです

 #include <iostream>
#include <cstdlib>
#include <new>
using namespace std;

class loc {
  int longitude, latitude;
public:
  loc() {longitude = latitude = 0;}
  loc(int lg, int lt) {
    longitude = lg;
    latitude = lt;
  }

  void show() {
    cout << longitude << " ";
    cout << latitude << "\n";
  }

  void *operator new(size_t size);
  void operator delete(void *p);

  void *operator new[](size_t size);
  void operator delete[](void *p);
};

// new overloaded relative to loc.
void *loc::operator new(size_t size)
{
void *p;

  cout << "In overloaded new.\n";
  p =  malloc(size);
  if(!p) {
    bad_alloc ba;
    throw ba;
  }
  return p;
}

// delete overloaded relative to loc.
void loc::operator delete(void *p)
{
  cout << "In overloaded delete.\n";
  free(p);
}

// new overloaded for loc arrays.
void *loc::operator new[](size_t size)
{
  void *p;

  cout << "Using overload new[].\n";
  p =  malloc(size);
  if(!p) {
    bad_alloc ba;
    throw ba;
  }
  return p;
}

// delete overloaded for loc arrays
void loc::operator delete[](void *p)
{
  cout << "Freeing array using overloaded delete[]\n";
  free(p);
}

int main()
{
  loc *p1, *p2;
  int i;

  try {
    p1 = new loc (10, 20); // allocate an object
  } catch (bad_alloc xa) {
    cout << "Allocation error for p1.\n";
    return 1;;
  }

  try {
    p2 = new loc [10]; // allocate an array
  } catch (bad_alloc xa) {
    cout << "Allocation error for p2.\n";
    return 1;;
  }

  p1->show();

  for(i=0; i<10; i++)
    p2[i].show();

  delete p1; // free an object
  delete [] p2; // free an array

  return 0;
}

メインの行 では、なぜ「。」p2[i].show();を使用しているのですか?. 「->」の代わりに.答えは配列になったということですか?それは本当ですか. ポインター p3 をポインター p2 にすることはできますか? 宣言するような

loc *p1,*p2,**p3;
p3=&p2;

しかし、その後、p3 を介して結果を表示する方法は次のように表示する必要がありますp3[i]->show()

4

3 に答える 3

1

ではない正確に。配列は、同じ型のオブジェクトが次々に格納されたシーケンスです。「オブジェクトのアドレス」のポインター。

あなたが観察した偶然の一致は、次の 2 つの事実の結果です。

  • 配列は、関数に渡されると「最初の要素へのポインター」に崩壊し、...
  • 疑似T& operator[](T* p, int i)は、コンパイラによって本質的に次のように実装されます。return *(p+i);

結果として、一連の同一オブジェクトを保存し、開始アドレスがある場合、[] 演算子は i 番目のオブジェクトにつながります。また、配列の開始アドレスは最初の要素のアドレスであり、暗黙的な配列からポインターへの変換によって取得されるため、2 つの式が実質的に一致していることがわかります。

しかし、偶然はそこで止まります。

ポインターを指すことについては、その概念を完全に理解していることを確認してください。

  • 別のポインターが同じ配列を指すようにしたい (配列アドレスを別のポインターに割り当てるか、最初のポインターを別のポインターに割り当てるだけです)
  • 配列を指すポインターを指すポインターが必要です。これは二重間接参照です。「ポインターへのポインター」が必要で、それに最初のポインターのアドレスを割り当てます(配列ではありません)

より明確にするために、次のようにします。

int a[5] = { 10,11,12,13,14 }; //5 integer named "a"
int* p = a; // p points to a[0], hence *p and p[0] gives 10, p[1] give 11
int* q = p+1; // q points to one after p (hence to 11), *q and q[0] are 11, q[1] 12 ...
int** d = &p; // d points to p, hence **d is 10 (*d)[1] 11 etc.

あなたが観察したハングはd[3]、整数の 13 ではなく、3 番目int*(pdを指すか) であるという事実によるものです。しかしp、単一の変数であるため、そのようなオブジェクトは存在しないため、結果は未定義です。(ハングしたのは幸運でした: 最悪の場合、正しいように見えるランダムな結果が得られ、エラーが隠されます!)。

あなたの特定のケースでは、 (p3が指すもの)後p3[i]->showにメモリiポインタに偶発的に格納された値を取得し、そのランダムアドレスで想定されるオブジェクトのメソッドを実行しようとします。そのため、ローカル変数にアクセスできません。p2pointer to locshowlocshowlongitude

結果は、実質的にすべて、p3[i] に存在するランダム データに依存します。

于 2013-08-24T07:10:18.807 に答える