★ 2 指標和引用
阿新 • • 發佈:2021-02-13
技術標籤:基礎學習 - C++c++
文章目錄
★ 指標和引用
1 引用的基本定義
n
是m
的一個引用(reference),m
是被引用物(referent)。
int m;
int &n = m;
n
相當於 m
的別名(綽號),對 n
的任何操作就是對 m
的操作。
所以 n
既不是 m
的拷貝,也不是指向 m
的指標,其實 n
就是 m
它自己。
#include <iostream>
int main()
{
using namespace std;
int a = 1;
int& b = a;
cout << "a:address->" << &a << endl;
cout << "b:address->" << &b << endl;
return 0;
}
引用的規則:
- 引用被建立的同時必須被初始化(指標則可以在任何時候被初始化)。
- 不能有
NULL
引用,引用必須與合法的儲存單元關聯(指標則可以是NULL
)。 - 一旦引用被初始化,就不能改變引用的關係(指標則可以隨時改變所指的物件)。
以下示例程式中,k
被初始化為 i
的引用。
語句 k = j
並不能將 k
修改成為 j
的引用,只是把 k
的值改變成為 6
。
由於 k
是 i
的引用,所以 i
的值也變成了 6
。
int i = 5;
int j = 6;
int &k = i;
k = j; // k 和 i 的值都變成了 6
引用的主要功能是傳遞函式的引數和返回值。
引用的const
#include <iostream>
int main()
{
using namespace std;
int d1 = 4;
const int& d2 = d1;
d1 = 5; //d1改變,d2的值也會改變。
cout << "d1: " << d1 << endl;
cout << "d2: " << d2 << endl << endl;
// d2 = 6;// 不能給常量(不能被修改的量)賦值。
const int d3 = 1;
const int& d4 = d3;
// int& d5 = d3; // 無法從“const int”轉換為“int &”
const int& d6 = 5; //常量具有常性,只有常引用可以引用常量
cout << "d3: " << d3 << endl;
cout << "d4: " << d4 << endl;
cout << "d6: " << d6 << endl << endl;
double d7 = 1.1;
// int& d8 = d7; // d7是double型別,d8是int,d7賦值給 d8時要生成一個臨時變數
// 也就是說d8引用的是這個帶有常性的臨時變數,所以不能賦值。
const int& d9 = d7; // 警告“初始化”: 從“double”轉換到“const int”,可能丟失資料
cout << "d7: " << d7 << endl;
cout << "d9: " << d9 << endl << endl;
return 0;
}
2 函式引數和返回值的傳遞
C++ 語言中,函式的引數和返回值的傳遞方式有三種:值傳遞、指標傳遞和引用傳遞。
- 以下是"值傳遞"的示例程式。
由於 Func1
函式體內的 x
是外部變數 n
的一份拷貝,改變 x
的值不會影響 n
, 所以 n
的值仍然是 0
。
#include <iostream>
void Func1(int x);
int main()
{
using namespace std;
int n = 0;
Func1(n);
cout << "n = " << n << endl;
return 0;
}
void Func1(int x)
{
x = x + 10;
}
- 以下是"指標傳遞"的示例程式。
由於 Func2
函式體內的 x
是指向外部變數 n
的指標,改變該指標的內容將導致 n
的值改變,所以 n
的值成為 10
。
#include <iostream>
void Func2(int* x);
int main()
{
using namespace std;
int n = 0;
Func2(&n);
cout << "n = " << n << endl;
return 0;
}
void Func2(int* x)
{
*x = *x + 10;
}
- 以下是"引用傳遞"的示例程式。
由於 Func3
函式體內的 x
是外部變數 n
的引用,x
和 n
是同一個東西,改變 x
等於改變 n
,所以 n
的值成為 10
。
#include <iostream>
void Func3(int& x);
int main()
{
using namespace std;
int n = 0;
Func3(n);
cout << "n = " << n << endl;
return 0;
}
void Func3(int& x)
{
x = x + 10;
}
3 引用和指標的區別
- 指標是一個變數,只不過這個變數儲存的是一個地址,指向記憶體的一個儲存單元;而引用僅是個別名;
- 引用使用時無需解引用,指標需要解引用(
*
); - 引用只能在定義時被初始化一次,之後不可變;指標可變;
- 引用不能為空,指標可以為空(
NULL
); - “
sizeof 引用
”得到的是所指向的變數(物件)的大小,而“sizeof 指標”
得到的是指標本身的大小; - 指標可以有多級,但是引用只能是一級(
int** p
合法 而int&& a
是不合法的) - 從記憶體分配上看:程式為指標變數分配記憶體區域,而引用不需要分配記憶體區域。
#include <iostream>
#include <string>
int main()
{
/** 指標和引用的例子 **/
std::string s1 = "蘿蔔";
std::string s2 = "青菜";
std::string s3 = "雞蛋";
std::string s4 = "西紅柿";
/** 指標可以初始化為空 **/
std::string* p_Str = NULL;
p_Str = &s2; // 初始化指標
/** 引用一開始必須初始化 **/
std::string& r_Str = s1;
std::cout << "我是指標" << *p_Str << std::endl; /** 青菜 **/
std::cout << "我是引用" << r_Str << std::endl; /** 蘿蔔 **/
std::cout << std::endl;
std::cout << "*********分別修改指標和引用***********" << std::endl;
r_Str = s3; /** 試圖讓r_Str為s3的別名 **/
p_Str = &s4; /** p_Str重新指向了s4 **/
std::cout << "我是指標" << *p_Str << std::endl; /** 西紅柿 **/
std::cout << "我是引用" << r_Str << std::endl; /** 雞蛋 **/
std::cout << std::endl;
std::cout << "*********檢視剛剛的修改對最初初始化的影響***********" << std::endl;
std::cout << "我是s1" << s1 << std::endl; /** 雞蛋 !!!注意 !!! **/
std::cout << "我是s2" << s2 << std::endl; /** 青菜 **/
std::cout << "我是s3" << s3 << std::endl; /** 雞蛋 **/
std::cout << "我是s4" << s4 << std::endl; /** 西紅柿 **/
return 0;
}