1. 程式人生 > 其它 >★ 2 指標和引用

★ 2 指標和引用

技術標籤:基礎學習 - C++c++

大綱目錄

文章目錄


★ 指標和引用

1 引用的基本定義

nm的一個引用(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; }

在這裡插入圖片描述

引用的規則:

  1. 引用被建立的同時必須被初始化(指標則可以在任何時候被初始化)。
  2. 不能有 NULL 引用,引用必須與合法的儲存單元關聯(指標則可以是 NULL)。
  3. 一旦引用被初始化,就不能改變引用的關係(指標則可以隨時改變所指的物件)。

以下示例程式中,k 被初始化為 i 的引用。

語句 k = j 並不能將 k 修改成為 j 的引用,只是把 k 的值改變成為 6

由於 ki 的引用,所以 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 的引用,xn 是同一個東西,改變 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 引用和指標的區別

  1. 指標是一個變數,只不過這個變數儲存的是一個地址,指向記憶體的一個儲存單元;而引用僅是個別名;
  2. 引用使用時無需解引用,指標需要解引用(*);
  3. 引用只能在定義時被初始化一次,之後不可變;指標可變;
  4. 引用不能為空,指標可以為空(NULL);
  5. sizeof 引用”得到的是所指向的變數(物件)的大小,而“sizeof 指標”得到的是指標本身的大小;
  6. 指標可以有多級,但是引用只能是一級(int** p合法 而 int&& a是不合法的)
  7. 從記憶體分配上看:程式為指標變數分配記憶體區域,而引用不需要分配記憶體區域。
#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;
}

在這裡插入圖片描述