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

我们应该像这样显示p3[i]->show()吗?

不。在这一行中,您正在尝试访问p3 + i内存地址。这会导致未定义的行为。你应该使用

(*p3)[i].show()

p3[i]->show()如果p3[i]持有指针,您应该使用。

于 2013-08-24T07:04:39.070 回答
1

不完全是。数组是一系列相同类型的对象一个接一个地存储。“对象地址”中的指针。

您观察到的巧合是两个事实的结果:

  • 当给函数时,数组衰减为“指向第一个元素的指针”,并且......
  • T& operator[](T* p, int i)由编译器本质上实现为return *(p+i);

因此,无论您存储一系列相同的对象,并且您有一个起始地址,[] 运算符都会将您引导到第 i 个对象。并且由于数组的起始地址是第一个元素的地址,并且是通过隐式数组到指针的转换获得的,因此您观察到两个表达式的实质重合。

但巧合就止步于此。

关于指向指针,请确保您完全理解这个概念:顺便问一下,不清楚是否:

  • 您希望另一个指针指向同一个数组(只需将数组地址分配给另一个指针或将第一个指针分配给另一个指针
  • 你想要一个指向指向数组的指针的指针:这是一个双重间接。您需要一个“指向指针的指针”并将其分配给它的第一个指针(不是数组)的地址

更清楚一点:

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,而是int*之后的第三个pd指向什么)。但是p只是一个变量,没有这样的对象,因此结果是未定义的。(你很幸运,它挂了:在最坏的情况下,你会得到一个随机结果,甚至看起来是正确的,从而隐藏了错误!)。

在您的特定情况下,p3[i]->show将值偶然存储在内存i指针中p2(p3 指向的内容)将其视为 apointer to loc并尝试在该随机地址执行show假定loc对象的方法,很可能不属于您的程序内存空间,所以show无法访问longitude局部变量。

结果 - 基本上 - 都取决于 p3[i] 中存在的随机数据。

于 2013-08-24T07:10:18.807 回答
0

为什么我们使用“.”。而不是“->”?难道答案是它变成了数组?

因为 p2[i] 实际上是 loc 的一个实例,而不是一个指向 loc 的指针;"loc *p2"p2 是指向 loc 的指针,而不是数组,它不会变成数组。

我们可以让指针说 p3 指向指针 p2 吗?

是的,这是合法的。但是 make p2 在你的现实世界项目中首先被初始化(而不是一个悬空指针)。

于 2013-08-24T07:00:53.873 回答