什麼是結構體?
簡單的來說,結構體就是一個可以包含不同數據類型的一個結構,它是一種可以自己定義的數據類型,它的特點和數組主要有兩點不同,首先結構體可以在一個結構中聲明不同的數據類型,第二相同結構的結構體變量是可以相互賦值的,而數組是做不到的,因為數組是單一數據類型的數據集合,它本身不是數據類型(而結構體是),數組名稱是常量指針,所以不可以做為左值進行運算,所以數組之間就不能通過數組名稱相互復制了,即使數據類型和數組大小完全相同。
定義結構體使用struct修飾符,例如:
struct test
{
float a;
int b;
};
上面的代碼就定義了一個名為test的結構體,它的數據類型就是test,它包含兩個成員a和b,成員a的數據類型為浮點型,成員b的數據類型為整型。
由於結構體本身就是自定義的數據類型,定義結構體變量的方法和定義普通變量的方法一樣。
test pn1;
這樣就定義了一test結構體數據類型的結構體變量pn1,結構體成員的訪問通過點操作符進行,pn1.a=10 就對結構體變量pn1的成員a進行了賦值操作。
注意:結構體生命的時候本身不占用任何內存空間,只有當你用你定義的結構體類型定義結構體變量的時候計算機才會分配內存。
結構體,同樣是可以定義指針的,那麼結構體指針就叫做結構指針。
結構指針通過->符號來訪問成員,下面我們就以上所說的看一個完整的例子:
#include <ioseam>
#include <sing>
using namespace s;
struct test//定義一個名為test的結構體
{
int a;//定義結構體成員a
int b;//定義結構體成員b
};
void main()
{
test pn1;//定義結構體變量pn1
test pn2;//定義結構體變量pn2
pn2.a=10;//通過成員操作符.給結構體變量pn2中的成員a賦值
pn2.b=3;//通過成員操作符.給結構體變量pn2中的成員b賦值
pn1=pn2;//把pn2中所有的成員值復制給具有相同結構的結構體變量pn1
cout<<pn1.a<<"|"<<pn1.b<<endl;
cout<<pn2.a<<"|"<<pn2.b<<endl;
test *point;//定義結構指針
point=&pn2;//指針指向結構體變量pn2的內存地址
cout<<pn2.a<<"|"<<pn2.b<<endl;
point->a=99;//通過結構指針修改結構體變量pn2成員a的值
cout<<pn2.a<<"|"<<pn2.b<<endl;
cout<<point->a<<"|"<<point->b<<endl;
cin.get();
}
總之,結構體可以描述數組不能夠清晰描述的結構,它具有數組所不具備的一些功能特性。下面我們來看一下,結構體變量是如何作為函數參數進行傳遞的。
#include <ioseam>
#include <sing>
using namespace s;
struct test
{
char name[10];
float socre;
};
void print_score(test pn)//以結構變量進行傳遞
{
cout<<pn.name<<"|"<<pn.socre<<endl;
}
void print_score(test *pn)//一結構指針作為形參
{
cout<<pn->name<<"|"<<pn->socre<<endl;
}
void main()
{
test a[2]={{"marry",88.5},{"jarck",98.5}};
int num = sizeof(a)/sizeof(test);
for(int i=0;i<num;i )
{
print_score(a[i]);
}
for(int i=0;i<num;i )
{
print_score(&a[i]);
}
cin.get();
}
void print_score(test *pn)的效率是要高過void print_score(test pn)的,因為直接內存操作避免了棧空間開辟結構變量空間需求,節省內存。
下面我們再說一下,傳遞結構引用的例子。
利用引用傳遞的好處很多,它的效率和指針相差無幾,但引用的操作方式和值傳遞幾乎一樣,種種優勢都說明善用引用可以做到程序的易讀和易操作,它的優勢尤其在結構和大的時候,避免傳遞結構變量很大的值,節省內存,提高效率。
#include <ioseam>
#include <sing>
using namespace s;
struct test
{
char name[10];
float socre;
};
void print_score(test &pn)//以結構變量進行傳遞
{
cout<<pn.name<<"|"<<pn.socre<<endl;
}
void main()
{
test a[2]={{"marry",88.5},{"jarck",98.5}};
int num = sizeof(a)/sizeof(test);
for(int i=0;i<num;i )
{
print_score(a[i]);
}
cin.get();
}
上面我們說明了易用引用對結構體進行操作的優勢,下面我們重點對比兩個例程,進一部分析關於效率的問題。
//-------------------------------------例程1---------------------------------
#include <ioseam>
#include <sing>
using namespace s;
struct test
{
char name[10];
float socre;
};
void print_score(test &pn)
{
cout<<pn.name<<"|"<<pn.socre<<endl;
}
test get_score()
{
test pn;
cin>>pn.name>>pn.socre;
return pn;
}
void main()
{
test a[2];
int num = sizeof(a)/sizeof(test);
for(int i=0;i<num;i )
{
a[i]=get_score();
}
cin.get();
for(int i=0;i<num;i )
{
print_score(a[i]);
}
cin.get();
}
//-------------------------------------例程2---------------------------------
#include <ioseam>
#include <sing>
using namespace s;
struct test
{
char name[10];
float socre;
};
void print_score(test &pn)
{
cout<<pn.name<<"|"<<pn.socre<<endl;
}
void get_score(test &pn)
{
cin>>pn.name>>pn.socre;
}
void main()
{
test a[2];
int num = sizeof(a)/sizeof(test);
for(int i=0;i<num;i )
{
get_score(a[i]);
}
cin.get();
for(int i=0;i<num;i )
{
print_score(a[i]);
}
cin.get();
}
例程2的效率要遠高過例程1的原因主要有以下兩處:
第一:
例程1中的
test get_score()
{
test pn;
cin>>pn.name>>pn.socre;
return pn;
}
調用的時候在內部要在棧空間開辟一個名為pn的結構體變量,程序pn的時候又再次在棧內存空間內自動生成了一個臨時結構體變量temp,在前面的教程中我們已經說過,它是一個copy,而例程2中的:
void get_score(test &pn)
{
cin>>pn.name>>pn.socre;
}
卻沒有這一過程,不開辟任何新的內存空間,也沒有任何臨時變量的生成。
第二:
例程1在mian()中,必須對返回的結構體變量進行一次結構體變量與結構體變量直接的相互賦值操作。
for(int i=0;i<num;i )
{
a[i]=get_score();
}
而例程2中由於是通過內存地址直接操作,所以完全沒有這一過程,提高了效率。
for(int i=0;i<num;i )
{
get_score(a[i]);
}
函數也是可以返回結構體應用的,例子如下:
#include <ioseam>
#include <sing>
using namespace s;
struct test
{
char name[10];
float socre;
};
test a;
test &get_score(test &pn)
{
cin>>pn.name>>pn.socre;
return pn;
}
void print_score(test &pn)
{
cout<<pn.name<<"|"<<pn.socre<<endl;
}
void main()
{
test &sp=get_score(a);
cin.get();
cout<<sp.name<<"|"<<sp.socre;
cin.get();
}
調用get_score(a);結束並返回的時候,函數內部沒有臨時變量的產生,返回直接吧全局結構變量a的內存地址賦予結構引用sp
最後提一下指針的引用
定義指針的引用方法如下:
void main()
{
int a=0;
int b=10;
int *p1=&a;
int *p2=&b;
int *&pn=p1;
cout <<pn<<"|"<<*pn<<endl;
pn=p2;
cout <<pn<<"|"<<*pn<<endl;
cin.get();
}
pn就是一個指向指針的引用,它也可以看做是指針別名,總之使用引用要特別注意它的特性,它的操作是和普通指針一樣的,在函數中對全局指針的引用操作要十分小心,避免破壞全局指針!