我正在编写一个程序,用于在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;
}
在 main 的 p2[i].show();
行中。为什么我们使用 "."。而不是 "->" 。答案是它变成了数组吗?这是真的吗?
我们可以让指针 p3 指向指针 p2 吗?
就像声明
loc *p1,*p2,**p3;
p3=&p2;
但是我们将如何通过p3显示结果。我们是否应该像p3[i]->show()
那样显示
当我累了的时候,程序就挂起了。
最佳答案
不完全是。数组是一系列依次存储的相同类型的对象。 “对象地址”中的指针。
您观察到的巧合是两个事实的结果:
- 当给函数时,数组会衰减为“指向第一个元素的指针”,并且......
- 伪
T& 运算符[](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,而是 p
之后的第三个 int*
(d
指向什么)。但由于 p
只是一个变量,因此不存在这样的对象,因此结果是未定义的。 (你很幸运它挂了:在最坏的情况下,你会得到一个甚至看起来正确的随机结果,从而隐藏了错误!)。
在您的具体情况下,p3[i]->show
采用p2
之后顺便存储在内存i
指针中的值(什么p3 指向)将其视为指向 loc 的指针,并尝试在该随机地址执行假定的 loc 对象的 show 方法,大多数情况下可能不属于您的程序内存空间,因此 show
无法访问 longitude
局部变量。
结果基本上全部取决于 p3[i] 中存在的随机数据。
关于c++ - 重载数组中的new和delete,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18415865/