引用
&符在不同情況下有不同的意義例如最常見的兩種邏輯與和按位與操作
現在我們將的是它表示引用的操作
目前爲了便於理解,將引用當成變量的別名理解,實際時在底層處理時被翻譯成了指針進行操作。
char &x=a;
這相當於給a的空間定義了另一個名字叫做x。需要注意的是,在使用引用是它的對象需要已被初始化,所以引用的使用是沒有空引用的。還需要注意的是引用不像指針沒有二級引用或者三級引用。
例如
char &x=a;
char &&y=x;
上面兩個引用所指向的是同一個空間,都是指向了a的內存空間。它不想二級指針會指向一級指針,然後一級指針指向變量。
還需要解釋的是引用是在編譯階段進行的,
例如:
void fun(int &a)
{
int *p=&a;
a+=1-;
*p+=10;
}
上面的函數在編譯過程中會被解釋爲
void fun(int *const a)
{
int *p=&a;
*a+=10;
*p+=10;
}
編譯器會把引用的參數處理爲被const修飾的不可更改指向的指針
所以引用和指針的使用在編程的角度來看是有區別的包括用法和使用方法之類,但是在編譯器的角度來看時,他們在底層的操作是相同的這可以從彙編語句中看到他們的操作是一樣的。
另外解釋一個使用引用的交換函數:
void swap(int &a, int &b) 之所以要加&符號是因爲,如果沒有添加的話相當於把兩個形參在另一個棧幀裏進行了交換,但是對main函數的棧幀中的數據沒有影響。
有一個引用符號&。有了這個相當於a,b就是x,y的別名。調用函數會將x,y 分別代替了a,b了,我們稱a,b分別引用了x,y變量。這樣函數裏頭操作的其實就是實參x,y本身了,也就是說函數裏是可以直接修改到x,y的值了。
再傳指針時需要進行判空,但是引用不需要,因爲不存在空引用
void swap(int &a, int &b)
{
//assert(x!=NULL)這是在指針調用時判空的斷言寫法,再使用前需要預編譯
#include<assert.h>
//他的作用和if(x==NULL) return NULL;時一個作用
int x = a;
a = b;
b = x;
}
void main()
{
int x = 10, y = 20;
//int &b = a;//相當於給a取了另一個名字叫做b,那麼int *p=&a和int *p=&b是一個意思
//int &c 這樣的做法是錯誤的 沒有空引用,同時也沒有二級引用
swap(a, b);
}
上面的實例中有
Assert
Assert是斷言的意思,頭文件爲assert.h,
assert是一個宏,他在DEBUG版本中產生作用,Release版本中失效
assert宏的原型定義在assert.h中,其作用是如果它的條件返回錯誤,則終止程序執行.
每個assert只檢驗一個條件,因爲同時檢驗多個條件時,如果斷言失敗,無法直觀的判斷是哪個條件失敗**
struct student
{
char name[30];
int num;
int grade[5];
};//name=>"yhping" num=>5 grade=>100,90,89,90,78
void intstudent(student*x)
{
assert(x != NULL);//通過斷言來判斷在指針調用時是否出現空指針
x->num = 5;
int ar[5] = { 100, 90, 89, 90, 78 };
memmove(x->grade, ar,sizeof(ar));//他的作用和memcpy他們的作用是一樣的,唯一的區別是,當內存發生局部重疊的時候,memmove保證拷貝的結果是正確的,memcpy不保證拷貝的結果的正確。
strcpy(x->name, "yhping");
}
void intstudent2(student&x)
{
x.num = 5;
int ar[5] = { 100, 90, 89, 90, 78 };
memmove(x.grade, ar, sizeof(ar));
strcpy(x.name, "yhping");
}
void main()
{
student s;
student s2;
intstudent(&s);
intstudent2(s);
}
在上面的程序中之所以使用memmove而不使用strcpy,是因爲我想對數組進行復制而不是字符串,不用strcpy是因爲在字符串的結尾處有’\0’,但是數組沒有。而且之所以不是有x.grade={100,89,92,90,78}
這是因爲大括號只能在初始化數組時才能使用,但是在x.grade定義完後,就不能這麼用了。