結構體的認識
- 結構體的定義
將不同數據類型的數據對象組織在一起。 - 結構體在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("\n1----Outputname,number,year,month,day\n"); for(i=0;i<4;i++)/*采用指針法輸出數組元素的各成員*/ printf("%20s%10ld%10d//%d//%d\n",(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;//記得釋放內存
版權聲明:本文為博主原創文章,未經博主允許不得轉載。