充当结构数组而不声明数组

Acts like an array of structs without declaring array

本文关键字:数组 声明 结构      更新时间:2023-10-16

我开始写这段代码是为了好玩,我很惊讶它编译和工作。(我正在使用开发C++进行编译。我想创建一个结构数组,但在我创建数组之前,它存储并读取值,就像它已经是一个数组一样。为什么会这样,我如何仍然可以创建一个结构数组,以便我可以跟踪数组的总大小?

#include <iostream>
using namespace std;
struct Shape
{
public:
int x,y,z;
};
struct Triangle: public Shape
{
public:
int tNum;
};
struct Rectangle: public Shape
{
public:
int rNum;
float differentNum;
};
struct Circle: public Shape
{
public:
int cNum;
}; 
int main(void)
{ int i;
Triangle tri;
Rectangle rec; 
Circle cir; 
Shape *arr[3]={&tri, &rec, &cir};
for(i=1;i<5;i++){ arr[1][i].x=i*2; cout<<"set  tri["<<i<<"] "<<i*2<<endl;} cout<<endl; 
for(i=1;i<5;i++){ arr[2][i].x=i*9; cout<<"set  rec["<<i<<"] "<<i*9<<endl;} cout<<"-----------------"<<endl;
for(i=1;i<5;i++){ cout<<"read tri["<<i<<"] "<<arr[1][i].x<<endl;} cout<<endl;
for(i=1;i<5;i++){ cout<<"read rec["<<i<<"] "<<arr[2][i].x<<endl;}
system("pause");
return(0);
}
/*output   
set  tri[1] 2   
set  tri[2] 4  
set  tri[3] 6  
set  tri[4] 8  
set  rec[1] 9  
set  rec[2] 18  
set  rec[3] 27  
set  rec[4] 36  
-----------------`  
read tri[1] 2  
read tri[2] 4  
read tri[3] 6  
read tri[4] 8
read rec[1] 9  
read rec[2] 18  
read rec[3] 27  
read rec[4] 36*/

您有一个包含 3 个Shape*变量的数组,每个变量都指向堆栈中一个有效的Shape实例:

  • arr[0]指向tri实例,因此arr[0][0]tri实例。
  • arr[1]指向rec实例,因此arr[1][0]rec实例。
  • arr[2]指向cir实例,因此arr[2][0]cir实例。

arr的任何其他使用基本上都是非法的(即使它可能有效)。

尽管不建议这样做,但rec实例和cir实例紧跟在tri实例之后出现在堆栈中这一事实允许您以其他几种方式使用arr并"保持活动状态":

  • arr[0][1]rec实例,显示在堆栈中tri实例之后。
  • arr[0][2]cir实例,显示在rec实例之后的堆栈中。
  • arr[1][1]cir实例,显示在rec实例之后的堆栈中。

正如下面的评论之一所指出的,这实际上取决于堆栈的实现。

任何其他(不同的)尝试通过arr访问内存都是潜在的内存访问冲突。

以下是您应该如何做到这一点:

#include <string>
using namespace std;
class Shape
{
protected:
Shape() {}
virtual ~Shape() {}
string type;
int x,y,z;
public:
string GetType() const {return type;}
void SetX(int val) {x = val;}
void SetY(int val) {y = val;}
void SetZ(int val) {z = val;}
};
class Triangle : public Shape
{
public:
Triangle():type("Triangle") {}
void SetNum(int val) {tNum = val;}
private:
int tNum;
};
class Rectangle : public Shape
{
public:
Rectangle():type("Rectangle") {}
void SetNum(int val) {rNum = val;}
void SetDifferentNum(float val) {differentNum = val;}
private:
int   rNum;
float differentNum;
};
class Circle : public Shape
{
public:
Circle():type("Circle") {}
void SetNum(int val) {cNum = val;}
private:
int cNum;
};
...
Triangle  tri;
Rectangle rec;
Circle    cir;
Shape*    arr[3] = {&tri, &rec, &cir};
int       size = sizeof(arr)/sizeof(*arr);
for (i=0; i<size; i++)
{
arr[i]->SetX(i*2);
cout << "set " << arr[i]->GetType() << "[" << i << "] = " << i*2 << endl;
}

你在这里发生了一些严重的未定义的行为;你的代码没有做你可能认为它正在做的事情。 例如,arr[2]是指向cir的指针,但arr[2][1]arr[2][2]是指向未初始化内存块的指针。 从您的定义

Shape *arr[3]={&tri, &rec, &cir};

您可以安全地访问arr[0](指向tri的指针)、arr[1](指向rec的指针)和arr[2](指向cir的指针),但仅此而已。