结构体的认识
- 结构体的定义
将不同数据类型的数据对象组织在一起。 - 结构体在c中和C++不同
在C中的结构体只能自定义数据类型,结构体中不允许有函数,而C++中的结构体可以加入成员函数。C中的结构体只涉及到数据结构,而不涉及到算法,也就是说在C中数据结构和算法是分离的,而到C++中一类或者一个结构体可以包含函数(这个函数在C++我们通常中称为成员函数),C++中的结构体和类体现了数据结构和算法的结合。
结构体的定义、初始化
- 一般结构体
struct test//定义一个名为test的结构体 { int a;//定义结构体成员a int b;//定义结构体成员b }; test pn1;//定义结构体变量pn1 test pn2;//定义结构体变量pn2 pn2.a=10;//通过成员操作符.给结构体变量pn2中的成员a赋值 pn2.b=3;//通过成员操作符.给结构体变量pn2中的成员b赋值 test* point;//定义结构指针 point=&pn2;//指针指向结构体变量pn2的内存地址 point->a=99;//通过结构指针修改结构体变量pn2成员a的值
- 含有指针
struct Student{ char *name; int score; struct Student* next; };
//重点记住,在结构体中含有指针需要为指针指定指向的内存地址 Student stu,*pStu; //结构体成员需要初始化 stu.name = new char;//stu.name = (char*)malloc(sizeof(char)); strcpy(stu.name,"ddd"); stu.score = 99; //结构体成员需要初始化 Pstu = new Student;//Pstu = malloc(sizeof(Student)); Pstu->name = new char//在用结构体指针的=时候先为整个结构体分配内存,然后再为结构体内部的指针申请内存。 //最后在根据那个地方new,然后进行delete delete stu.name; stu.name = null; delete Pstu.name; Pstu->name = null; delete Pstu; Pstu = null; //记住最后一定将指针赋值为null,防止指针乱指,成为野指针。
- 结构体嵌套
struct Data { int year; int month; int day; } struct stu /*定义结构体* / { char name[20]; long num; struct data birthday; /嵌*套的结构体类型成员*/ } ; //结构体初始化 struct stu a; a.name = "gaoqinag";//在声明的时候自动在栈为数组进行内存分配 a.birthday.year = 2013;//对于嵌套的结构体同样适用,自动 申请内存。 a.birthday.month = 12;
这样的结构体,成员指针或者分配内存,或者指向常量区,不然它们就都是野指针;分配内存的话,就要释放,分配内存的时候,是从外向里,即先分配结构体的指针,再分配成员指针,释放的时候,是从里向外,先释放成员指针,再释放结构体指针,顺序不能错的。总之每个malloc都要对应一个free,每一个new要对应一个delete!
结构体数组
structdata/*定义结构体类型*/ { intday,month,year; }; structstu/*定义结构体类型*/ { char name[20]; long num; struct data birthday; }; main() { inti; structstu*p,student[4]= { {"liying",1,1978,5,23}, {"wangping",2,1979,3,14}, {"libo",3,1980,5,6}, {"xuyan",4,1980,4,21} }; /*定义结构体数组并初始化*/ p=student;/*将数组的首地址赋值给指针p,p指向了一维数组student*/ printf(" 1----Outputname,number,year,month,day "); for(i=0;i<4;i++)/*采用指针法输出数组元素的各成员*/ printf("%20s%10ld%10d//%d//%d ",(p+i)->name,(p+i)->num, (p+i)->birthday.year,(p+i)->birthday.month, (p+i)->birthday.day); }
结构体作为函数参数
-
#include<iostream> #include<string> using namespace std; //结构体定义 struct Student{ string name; int score; }; int main(){ Student one; one.name="千手"; one.score=99; // 值传递演示 PrintByValue(one);//100 cout<<one.name<<endl; cout<<one.score<<endl;//验证 score的值是否加一了 //99 //参数为指针演示 Student *p=&one; PrintByHand(p);//100 cout<<one.name<<endl; cout<<one.score<<endl;//验证 score的值是否加一了 //100 //参数为引用演示 PrintByQuote(one);//101 cout<<one.name<<endl; cout<<one.score<<endl;//验证 score的值是否加一了 //101 return 0; } void PrintByValue(Student one){ cout<<one.name<<endl; cout<<++one.score<<endl;//在Print函数中,对score进行加一 } void PrintByHand(Student *p){ cout<<p->name<<endl; cout<<++p->score<<endl;//在Print函数中,对score进行加一 } void PrintByQuote(Student &one){ cout<<one.name<<endl; cout<<++one.score<<endl;//在Print函数中,对score进行加一 }
这种方式值采取的“值传递”的方式,将结构体变量所占的内存单元的内存全部顺序传递给形参。实际上在被调用函数,重新在栈中分配内存,将实参的值,进行赋值,在被调用函数操作时新申请内存的形参,和实参半点关系没有。采用值传递的方式,如果在函数被执行期间改变了形参的值,该值不能反映到主调函数中的对应的实参,这往往不能满足使用要求。因此一般较少使用这种方法。
- 参数为指针
这种方式虽然也是值传递的方式,但是这次传递的值却是指针。通过改变指针指向的结构体变量的值,可以间接改变实参的值。并且,在调用函数期间,仅仅建立了一个指针变量,大大的减小了系统的开销。
- 参数为引用
形参是对应的结构体类型的引用,虚实结合时传递的是地址,因而执行效率比较高。而且,与指针作为函数参数相比较,它看起来更加直观易懂。因而,引用变量作为函数参数,它可以提高效率,而且保持程序良好的可读性。
- 引用传递
上面讲解的是按值传递,按值传递就是将值传递进去,在函数中进行一些列操作,被调用函数中申请分配的内存不会传出来。
引用传递最重要的目的就是将被调用函数申请的内存进行获取,更准确将是内存的地址。
在这里讲解一个重点就是在被调用函数申请内存的时候,怎样从被调用函数这个传出这个结构体,这里要从内存分析。
在被调用函数进行内存分配后需要将内存的地址获取,而内存的地址往往是通过指针获取,另一方面形参中创建一个指针后,要与实参的指针建立联系。单纯进行 stu* p = stu *ptr;这样形参中对p进行操作和实参的*ptr半点关系没有,所以传入的二级指针。
void GetStu(Student** stu) { //这里做实验,如果先申请内存,然后在赋值给stu,其实改变stu指向,不再指向实参了,内存还是没有传出去 //Student *student = new Student; // student->name = "hahh"; // student->score = 80; // stu = &student; //这里直接获取形参中指向,也就是实参地址,为实参地址分配内存 *stu = new Student; (**stu).name = "ahha";//为实参中地址指向的内存赋值。 (**stu).score = 80; } Student *temp;//声明一个结构体指针 *temp->name = "hah"//程序会报错,没有给结构体指针变量赋值呢。 GetStu(&temp); cout<<(*temp).score<<endl; cout<<(*temp).name<<endl; cout<<temp->name<<endl; delete temp;//记得释放内存
版权声明:本文为博主原创文章,未经博主允许不得转载。