国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C++的指針和引用

這篇具有很好參考價(jià)值的文章主要介紹了C++的指針和引用。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

C++的指針和引用

C++指針

C++中內(nèi)存單元內(nèi)容和地址

  • 內(nèi)存由很多的內(nèi)存單元組成,這些內(nèi)存單元用于存放各種類型數(shù)據(jù);
  • 計(jì)算機(jī)對(duì)內(nèi)存的每個(gè)內(nèi)存單元都進(jìn)行了編號(hào),這個(gè)編號(hào)就稱為內(nèi)存地址,地址決定了內(nèi)存單元在內(nèi)存中的位置;
  • 記住這些內(nèi)存單元地址不方便,因此C++語(yǔ)言的編譯器讓我們通過(guò)名字來(lái)訪問(wèn)這些內(nèi)存位置;
int a = 112, b = -1;
float c = 3.14;
int *d = &a;
float *e = &c;

指針的定義和間接訪問(wèn)操作

  • 指針定義的基本形式:指針本身就是一個(gè)變量,其符合變量定義的基本形式,它存儲(chǔ)的是值的地址。對(duì)類型T,T*是"到T的指針"類型,一個(gè)類型為T*的變量能保存一個(gè)類型T的對(duì)象的地址.

  • 通過(guò)指針訪問(wèn)它所指向的地址的過(guò)程稱為間接訪問(wèn)或者引用指針;

    這個(gè)用于執(zhí)行間接訪問(wèn)操作符是單目操作符*; cout << *d << endl;

#include <iostream>
using namespace std;
int main()
{
	int a = 112, b = -1;
	float c = 3.14f;
	int*  d = &a;
	float*  e = &c;
	cout << d << endl;    cout << e << endl;
	cout << (*d) << endl;    cout << (*e) << endl;
	return 0;
}

關(guān)于變量、地址和指針變量:

  • 一個(gè)變量的三個(gè)重要信息:

    • 變量地址信息
    • 變量所存的信息
    • 變量類型
  • 指針變量是一個(gè)專門用來(lái)記錄變量的地址的變量;通過(guò)指針變量可以間接的訪問(wèn)另一個(gè)變量的值。

指針和數(shù)組

如過(guò)是數(shù)組,數(shù)組地址是不可改變的,但是數(shù)組值是可以改變的

指針地址是可變的,指針值是否可改變?nèi)Q于所指的區(qū)間的存儲(chǔ)區(qū)域是否可變

#include <iostream>
using namespace std;
int main()                              
{
	// T*:  注意*在定義和間接訪問(wèn)上的作用
	//int i = 4;  int* iP = &i;   cout << (*iP) << endl;
	//double d = 3.14; double* dP = &d; cout << (*dP) << endl;
	//char c = 'a';  char* cP = &c; cout << (*cP) << endl;
	
	// array of pointers和a pointer to an array
	int c[4] = { 0x80000000, 0xFFFFFFFF, 0x00000000, 0x7FFFFFFF };
	int*  a[4];                          // array of pointers       指針的數(shù)組
	int(*b)[4];                         // a pointer to an array 數(shù)組的指針
	b = &c;                            // 注意:這里數(shù)組個(gè)數(shù)得匹配
	// 將數(shù)組c中元素賦給數(shù)組a
	for (unsigned int i = 0; i<4; i++)
	{
		a[i] = &(c[i]);
	}
	// 輸出看下結(jié)果
	cout << *(a[0]) << endl;   // -2147483648
	cout << (*b)[3] << endl;   // 2147483647
	return 0;                            
}

左值和右值

  • 概念:

    一般說(shuō)法,編譯器為其單獨(dú)分配了一塊存儲(chǔ)空間,可以取其地址的,左值可以放在賦值運(yùn)算符左邊;

    右值指的是數(shù)據(jù)本身,不能取到自身地址,右值只能放在賦值運(yùn)算符右邊。

  • 具體分析:

? 左值最常見(jiàn)的情況如函數(shù)和數(shù)據(jù)成員的名字;

? 右值是沒(méi)有標(biāo)識(shí)符、不可取地址的表達(dá)式,一般稱之為臨時(shí)對(duì)象。

幾種C++中的原始指針

  • 一般類型指針T*;

? T是一個(gè)泛型,泛指任何一種類型

  • 指針的數(shù)組與數(shù)組的指針

    指針的數(shù)組 T *t[] 數(shù)組的指針 T(*t)[]

  • const pointer和pointer to const

    • 關(guān)于const修飾的部分
      • 看左側(cè)最近的部分
      • 如果左側(cè)沒(méi)有,則看右側(cè)
#include <iostream>
using namespace std;
unsigned int MAX_LEN = 11;
int main()
{
	char strHelloworld[] = { "helloworld" };
	char const* pStr1 = "helloworld";             // const char*
	char* const pStr2 = strHelloworld;          
	char const* const pStr3 = "helloworld";  // const char* const
	pStr1 = strHelloworld;
	//pStr2 = strHelloworld;                            // pStr2不可改
	//pStr3 = strHelloworld;                            // pStr3不可改
	unsigned int len = strnlen_s(pStr2, MAX_LEN);
	cout << len << endl;
	for (unsigned int index = 0; index < len; ++index)
	{
		//pStr1[index] += 1;                               // pStr1里的值不可改
		pStr2[index] += 1;
		//pStr3[index] += 1;                               // pStr3里的值不可改
	}
	return 0;
}
  • 指向指針的指針

    例子:

    int a = 123;

    int *b = &a;

    int **c = &b;

    • *操作符具有從右向左的結(jié)合性
    • **這個(gè)表達(dá)式相當(dāng)于*(*c) , 必須從里向外逐層求值
    • *c得到的是b的地址 **c相當(dāng)于*b,得到a的值
  • 未初始化和非法指針(野指針)

? 例子:int *a; // a的指向不明,可能會(huì)導(dǎo)致程序崩潰。

? *a = 12;

? 最壞的情況是定位到了一個(gè)可訪問(wèn)的地址,無(wú)意間修改了它,這樣的錯(cuò)誤難以捕捉,引發(fā)的錯(cuò)誤可能與原先用于操作的代碼完全不相干。

  • NULL指針

    一個(gè)特殊的指針變量,表示不指向任何東西 int *a = NULL;

    • NULL指針表示指針未指向任何東西
    • 對(duì)于一個(gè)指針,如果已經(jīng)知道將被初始化的地址,那么請(qǐng)賦值給它,否則請(qǐng)將它設(shè)置為NULL
    • 在對(duì)一個(gè)指針進(jìn)行間接引用的時(shí)候,請(qǐng)先判斷該指針是否為NULL。
  • 杜絕野指針:

    指向一堆垃圾內(nèi)存的指針。if等判斷對(duì)它們不起作用,因?yàn)闆](méi)有設(shè)置為NULL

    一般有三種情況:

    • 指針變量沒(méi)有初始化
    • 已經(jīng)釋放不用的指針沒(méi)有設(shè)置為NULL,如delete和free之后的指針
    • 指針操作超越了變量作用范圍

    使用注意事項(xiàng):

    • 沒(méi)有初始化的,不用的或者超出范圍的指針請(qǐng)把值置為NULL。
#include <iostream>
using namespace std;
int main()
{
	// 指針的指針
	int a = 123;
	int* b = &a;
	int** c = &b;
	// NULL 的使用
	int* pA = NULL;
	pA = &a;
	if (pA != NULL)  //  判斷NULL指針
	{
		cout << (*pA) << endl;
	}
	pA = NULL;       //  pA不用時(shí),置為NULL
    return 0;
}

原始指針的基本運(yùn)算

  • &與*操作符
#include <iostream>
using namespace std;
int main()
{
	char ch = 'a';
	// &操作符
	//&ch = 97;                      // &ch左值不合法
	char* cp = &ch;                // &ch右值
	//&cp = 97;                      // &cp左值不合法
	char** cpp = &cp;            // &cp右值
	// *操作符
	*cp = 'a';                           // *cp左值取變量ch位置
	char ch2 = *cp;                 // *cp右值取變量ch存儲(chǔ)的值
	//*cp + 1 = 'a';                 //  *cp+1左值不合法的位置
	ch2 = *cp + 1;                  //  *cp+1右值取到的字符做ASCII碼+1操作
	*(cp + 1) = 'a';                  //  *(cp+1)左值語(yǔ)法上合法,取ch后面位置
	ch2 = *(cp + 1);                //  *(cp+1)右值語(yǔ)法上合法,取ch后面位置的值
    return 0;
}
  • ++與–操作符
int main()
{
	char ch = 'a';
	char* cp = &ch;
	// ++,--操作符
	char* cp2 = ++cp;
	char* cp3 = cp++;
	char* cp4 = --cp;
	char* cp5 = cp--;
	// ++ 左值
	//++cp2 = 97;
	//cp2++ = 97;
	// *++, ++*
	*++cp2 = 98;
	char ch3 = *++cp2;
	*cp2++ = 98;
	char ch4 = *cp2++;
	// ++++, ----操作符等
	int a = 1, b = 2, c, d;
	//c = a++b;                  // error
	c = a++ + b;
	//d = a++++b;             // error
	char ch5 = ++*++cp;
    return 0;
}

存儲(chǔ)區(qū)域劃分

棧和隊(duì)列

  • 棧:先進(jìn)后出
  • 隊(duì)列:先進(jìn)先出

代碼在內(nèi)存單元中的分布

#include <string>
int a = 0;                                                //(GVAR)全局初始化區(qū) 
int* p1;                                                   //(bss)全局未初始化區(qū) 
int main()                                               //(text)代碼區(qū)
{
	int b=1;                                              //(stack)棧區(qū)變量 
	char s[] = "abc";                                 //(stack)棧區(qū)變量
	int*p2=NULL;                                     //(stack)棧區(qū)變量
	char *p3 = "123456";               //123456\0在常量區(qū), p3在(stack)棧區(qū)
	static int c = 0;                                   //(GVAR)全局(靜態(tài))初始化區(qū) 
	p1 = new int(10);                               //(heap)堆區(qū)變量
	p2 = new int(20);                               //(heap)堆區(qū)變量
	char* p4 = new char[7];                     //(heap)堆區(qū)變量
	strcpy_s(p4, 7, "123456");                  //(text)代碼區(qū)
	//(text)代碼區(qū)
	if (p1 != NULL)
	{
		delete p1;
		p1 = NULL;
	}
	if (p2 != NULL)
	{
		delete p2;
		p2 = NULL;
	}
	if (p4 != NULL)
	{
		delete[ ] p4;
		p4 = NULL;
	}
	//(text)代碼區(qū)
	return 0;                                            //(text)代碼區(qū)
}

從高地址到低地址

??臻g - 從高到低

堆空間 - 從低到高

cpp動(dòng)態(tài)分配資源和回收原則

動(dòng)態(tài)分配資源 – 堆(heap)

  1. 從現(xiàn)代編程語(yǔ)言角度,使用堆或者說(shuō)使用動(dòng)態(tài)內(nèi)存分配,是一件很自然的事情
  2. 動(dòng)態(tài)分配內(nèi)存帶來(lái)了不確定性:內(nèi)存分配耗時(shí)?失敗怎么辦?
  3. 一般而言,當(dāng)我們?cè)诙焉戏峙鋬?nèi)存時(shí),很多語(yǔ)言會(huì)使用new這樣的關(guān)鍵字,有些語(yǔ)言則是隱式分配。在C++中new的對(duì)應(yīng)詞是delete,因?yàn)镃++是可以讓程序員完全接管內(nèi)存分配釋放的。

內(nèi)存分配和回收原則:

程序通常需要牽涉到三個(gè)內(nèi)存管理器操作:

  • 分配一個(gè)某大小的內(nèi)存塊
  • 釋放一個(gè)之前分配的內(nèi)存塊
  • 垃圾收集操作,尋找不再使用的內(nèi)存塊并且予以釋放;

這個(gè)回收策略需要實(shí)現(xiàn)實(shí)時(shí)性、額外開(kāi)銷等各方面的平衡,很難有統(tǒng)一和高效的做法;

C++做了1, 2 兩件事;java做了1,3兩件事。

資源管理方案-RAII

  • C++所特有的的資源管理方式。
  • RAII依托棧和析構(gòu)函數(shù),來(lái)對(duì)所有資源(包括堆內(nèi)存在內(nèi))進(jìn)行管理。
  • RAII有些比較成熟的智能指針的代表:std::auto_ptr 等

C++中幾種變量對(duì)比

棧和堆中的變量對(duì)比:

棧區(qū) 堆區(qū)
作用域 函數(shù)體內(nèi),語(yǔ)句塊{}作用域 整個(gè)程序范圍內(nèi),由 new malloc開(kāi)始 , delete free結(jié)束
編譯期間大小確定 由變量大小范圍確定 變量大小范圍不確定,需要運(yùn)行時(shí)確定
大小范圍 windows默認(rèn)是1M linux是8M或者10M(可調(diào)整) 所有系統(tǒng)的堆內(nèi)存空間上限是接近內(nèi)存(虛擬內(nèi)存)的總大小的(一部分被OS占用)
內(nèi)存分配方式 地址由高到低 地址由低到高
內(nèi)容是否可變 可變 可變

全局靜態(tài)存儲(chǔ)區(qū)和常量存儲(chǔ)區(qū)的變量對(duì)比:

全局經(jīng)驗(yàn)存儲(chǔ)區(qū) 常量存儲(chǔ)區(qū)
存儲(chǔ)內(nèi)容 全局變量,靜態(tài)變量 常量
編譯期間大小是否確定 確定 確定
內(nèi)容是否可變 可變 不可變

內(nèi)存泄漏

  • 什么事內(nèi)存泄漏問(wèn)題:

指的是程序中已經(jīng)分配的堆內(nèi)存由于某種原因程序未釋放,造成系統(tǒng)內(nèi)存的浪費(fèi),導(dǎo)致程序運(yùn)行速度減慢甚至系統(tǒng)崩潰等嚴(yán)重后果。

  • 內(nèi)存泄漏發(fā)生的原因和排查方式:
    • 內(nèi)存泄漏主要發(fā)生在堆內(nèi)存分配方式中,即配置了內(nèi)存后,多有指向該內(nèi)存的指針都遺失了。若缺乏語(yǔ)言這樣的垃圾回收機(jī)制,這樣的內(nèi)存片無(wú)法歸還系統(tǒng)。
    • 因?yàn)閮?nèi)存泄漏屬于程序運(yùn)行中的問(wèn)題,無(wú)法 通過(guò)編譯識(shí)別,所以只能在程序運(yùn)行過(guò)程中來(lái)判斷。

智能指針

使用指針是非常危險(xiǎn)的行為,可能存在空指針,野指針的問(wèn)題,并且可能造成內(nèi)存泄漏問(wèn)題??芍羔樣址浅8咝В晕覀兿M愿踩姆绞絹?lái)使用指針。

  • 一般有兩種典型的方案:
    • 使用更安全的指針 - 智能指針
    • 不使用指針,使用更安全的方式 - 引用

C++的智能指針

  • C++中推出了常用的只能指針

unique_ptr、share_ptr、weak_ptr和C++11中已經(jīng)廢棄的auto_ptr(C++17中刪除)

  • 這里我們從應(yīng)用場(chǎng)景中來(lái)分析智能指針
  1. 應(yīng)用場(chǎng)景: 對(duì)象所有權(quán) 生命周期
  2. 性能分析
auto_ptr

由new expression獲得對(duì)象,在auto_ptr對(duì)象銷毀時(shí),它所管理的對(duì)象也會(huì)被自動(dòng)delete掉

所有權(quán)轉(zhuǎn)移:不小心把它傳遞給另外的智能指針,原來(lái)的指針就不再擁有這個(gè)對(duì)象了,在拷貝/賦值的過(guò)程中,會(huì)直接剝奪指針對(duì)內(nèi)存的控制權(quán),轉(zhuǎn)交給新對(duì)象,然后再將原對(duì)象置為nullptr

#include <string>
#include <iostream>
#include <memory>
using namespace std;
int main()
{
	{// 確定auto_ptr失效的范圍
		// 對(duì)int使用
		auto_ptr<int> pI(new int(10));
		cout << *pI << endl;                // 10 

		// auto_ptr	C++ 17中移除	擁有嚴(yán)格對(duì)象所有權(quán)語(yǔ)義的智能指針
		// auto_ptr原理:在拷貝 / 賦值過(guò)程中,直接剝奪原對(duì)象對(duì)內(nèi)存的控制權(quán),轉(zhuǎn)交給新對(duì)象,
		// 然后再將原對(duì)象指針置為nullptr(早期:NULL)。這種做法也叫管理權(quán)轉(zhuǎn)移。
		// 他的缺點(diǎn)不言而喻,當(dāng)我們?cè)俅稳ピL問(wèn)原對(duì)象時(shí),程序就會(huì)報(bào)錯(cuò),所以auto_ptr可以說(shuō)實(shí)現(xiàn)的不好,
		// 很多企業(yè)在其庫(kù)內(nèi)也是要求不準(zhǔn)使用auto_ptr。
		auto_ptr<string> languages[5] = {
			auto_ptr<string>(new string("C")),
			auto_ptr<string>(new string("Java")),
			auto_ptr<string>(new string("C++")),
			auto_ptr<string>(new string("Python")),
			auto_ptr<string>(new string("Rust"))
		};
		cout << "There are some computer languages here first time: \n";
		for (int i = 0; i < 5; ++i)
		{
			cout << *languages[i] << endl;
		}
		auto_ptr<string> pC;
		pC = languages[2]; // languges[2] loses ownership. 將所有權(quán)從languges[2]轉(zhuǎn)讓給pC,
		//此時(shí)languges[2]不再引用該字符串從而變成空指針
		cout << "There are some computer languages here second time: \n";
		for (int i = 0; i < 2; ++i)
		{
				cout << *languages[i] << endl;
		}
		cout << "The winner is " << *pC << endl;
		//cout << "There are some computer languages here third time: \n";
		//for (int i = 0; i < 5; ++i)
		//{
		//	cout << *languages[i] << endl;
		//}
	}
	return 0; 
}
unique_ptr

unique_ptr是專屬版本,所以u(píng)nique_ptr管理的內(nèi)存,只能被一個(gè)對(duì)象持有,不支持復(fù)制和賦值

移動(dòng)語(yǔ)義:unique_ptr禁止了拷貝語(yǔ)義,但有時(shí)我們也需要能夠轉(zhuǎn)移所有權(quán),于是提供了移動(dòng)語(yǔ)義,即可以使用std::move()進(jìn)行控制所有權(quán)的轉(zhuǎn)移。

#include <memory>
#include <iostream>
using namespace std;
int main()
{
	// 在這個(gè)范圍之外,unique_ptr被釋放
	{
		auto i = unique_ptr<int>(new int(10));
		cout << *i << endl;
	}

	// unique_ptr
	auto w = std::make_unique<int>(10);
	cout << *(w.get()) << endl;                             // 10
	//auto w2 = w; // 編譯錯(cuò)誤如果想要把 w 復(fù)制給 w2, 是不可以的。
	//  因?yàn)閺?fù)制從語(yǔ)義上來(lái)說(shuō),兩個(gè)對(duì)象將共享同一塊內(nèi)存。

	// unique_ptr 只支持移動(dòng)語(yǔ)義, 即如下
	auto w2 = std::move(w); // w2 獲得內(nèi)存所有權(quán),w 此時(shí)等于 nullptr
	cout << ((w.get() != nullptr) ? (*w.get()) : -1) << endl;       // -1
	cout << ((w2.get() != nullptr) ? (*w2.get()) : -1) << endl;   // 10
    return 0;
}
share_ptr 和 weak_ptr

share_ptr通過(guò)一個(gè)引用計(jì)數(shù)共享一個(gè)對(duì)象。

share_ptr是為了解決auto_ptr在對(duì)象所有權(quán)上的局限性,在使用引用計(jì)數(shù)的機(jī)制上提供了可以共享所有權(quán)的智能指針,當(dāng)然這需要額外的開(kāi)銷。

當(dāng)引用計(jì)數(shù)為0的時(shí)候,該對(duì)象沒(méi)有被使用,可以進(jìn)行析構(gòu)。

  • 循環(huán)引用的問(wèn)題:引用計(jì)數(shù)會(huì)帶來(lái)循環(huán)引用的問(wèn)題,造成內(nèi)存無(wú)法正?;厥?,造成內(nèi)存泄漏。

weak_ptr被設(shè)計(jì)為與share_ptr共同工作,用一種觀察者模式工作。

作用是協(xié)助share_ptr工作,可獲得資源的觀測(cè)權(quán),像旁觀者那樣觀測(cè)資源使用情況。觀察者意味著weak_ptr只對(duì)share_ptr進(jìn)行引用,而不改變其引用計(jì)數(shù),當(dāng)被觀察的share_ptr失效后相應(yīng)的weak_ptr也會(huì)失效。

#include <iostream>
#include <memory>
using namespace std;
int main()
{
	 shared_ptr 
	//{
	//	//shared_ptr 代表的是共享所有權(quán),即多個(gè) shared_ptr 可以共享同一塊內(nèi)存。
	//	auto wA = shared_ptr<int>(new int(20));
	//	{
	//		auto wA2 = wA;
	//		cout << ((wA2.get() != nullptr) ? (*wA2.get()) : -1) << endl;       // 20
	//		cout << ((wA.get() != nullptr) ? (*wA.get()) : -1) << endl;           // 20
	//		cout << wA2.use_count() << endl;                                              // 2
	//		cout << wA.use_count() << endl;                                                // 2
	//	}
	//	//cout << wA2.use_count() << endl;                                               
	//	cout << wA.use_count() << endl;                                                    // 1
	//	cout << ((wA.get() != nullptr) ? (*wA.get()) : -1) << endl;               // 20
	//	//shared_ptr 內(nèi)部是利用引用計(jì)數(shù)來(lái)實(shí)現(xiàn)內(nèi)存的自動(dòng)管理,每當(dāng)復(fù)制一個(gè) shared_ptr,
	//	//	引用計(jì)數(shù)會(huì) + 1。當(dāng)一個(gè) shared_ptr 離開(kāi)作用域時(shí),引用計(jì)數(shù)會(huì) - 1。
	//	//	當(dāng)引用計(jì)數(shù)為 0 的時(shí)候,則 delete 內(nèi)存。
	//}

	// move 語(yǔ)法
	auto wAA = std::make_shared<int>(30);
	auto wAA2 = std::move(wAA); // 此時(shí) wAA 等于 nullptr,wAA2.use_count() 等于 1
	cout << ((wAA.get() != nullptr) ? (*wAA.get()) : -1) << endl;          // -1
	cout << ((wAA2.get() != nullptr) ? (*wAA2.get()) : -1) << endl;      // 30
	cout << wAA.use_count() << endl;                                                  // 0
	cout << wAA2.use_count() << endl;                                                // 1
	//將 wAA 對(duì)象 move 給 wAA2,意味著 wAA 放棄了對(duì)內(nèi)存的所有權(quán)和管理,此時(shí) wAA對(duì)象等于 nullptr。
	//而 wAA2 獲得了對(duì)象所有權(quán),但因?yàn)榇藭r(shí) wAA 已不再持有對(duì)象,因此 wAA2 的引用計(jì)數(shù)為 1。

    return 0;
}
#include <string>
#include <iostream>
#include <memory>
using namespace std;

struct B;
struct A {
	shared_ptr<B> pb;
	~A()
	{
		cout << "~A()" << endl;
	}
};
struct B {
	shared_ptr<A> pa;
	~B()
	{
		cout << "~B()" << endl;
	}
};

// pa 和 pb 存在著循環(huán)引用,根據(jù) shared_ptr 引用計(jì)數(shù)的原理,pa 和 pb 都無(wú)法被正常的釋放。
// weak_ptr 是為了解決 shared_ptr 雙向引用的問(wèn)題。
struct BW;
struct AW
{
	shared_ptr<BW> pb;
	~AW()
	{
		cout << "~AW()" << endl;
	}
};
struct BW
{
	weak_ptr<AW> pa;
	~BW()
	{
		cout << "~BW()" << endl;
	}
};

void Test()
{
	cout << "Test shared_ptr and shared_ptr:  " << endl;
	shared_ptr<A> tA(new A());                                               // 1
	shared_ptr<B> tB(new B());                                                // 1
	cout << tA.use_count() << endl;
	cout << tB.use_count() << endl;
	tA->pb = tB;
	tB->pa = tA;
	cout << tA.use_count() << endl;                                        // 2
	cout << tB.use_count() << endl;                                        // 2
}
void Test2()
{
	cout << "Test weak_ptr and shared_ptr:  " << endl;
	shared_ptr<AW> tA(new AW());
	shared_ptr<BW> tB(new BW());
	cout << tA.use_count() << endl;                                        // 1
	cout << tB.use_count() << endl;                                        // 1
	tA->pb = tB;
	tB->pa = tA;
	cout << tA.use_count() << endl;                                        // 1
	cout << tB.use_count() << endl;                                        // 2
}

int main()
{
	Test();
	Test2();
    return 0;
}

C++的引用

引用是什么?變量的別名,是一種特殊的指針,不允許修改的指針。

使用指針有哪些坑:

  1. 空指針
  2. 野指針
  3. 不知不覺(jué)改變了指針的值,卻繼續(xù)使用

使用引用則可以:

  1. 不存在空引用
  2. 必須初始化
  3. 一個(gè)引用永遠(yuǎn)指向它的初始化的那個(gè)對(duì)象
  • 基本使用:可以認(rèn)為是變量的別名,使用時(shí)候可以認(rèn)為是變量本身

有了指針為什么還要有引用?

為了支持運(yùn)算符重載。

有了引用為什么還需要指針?

為了兼容C語(yǔ)言。

#include <iostream>
#include <assert.h>
using namespace std;

// 編寫一個(gè)函數(shù),輸入兩個(gè)int型變量a,b
// 實(shí)現(xiàn)在函數(shù)內(nèi)部將a,b的值進(jìn)行交換。
void swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}
void swap2(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

int main()
{
	//int x = 1, x2 = 3;
	//int& rx = x;
	//rx = 2;
	//cout << x << endl;
	//cout << rx << endl;
	//rx = x2;
	//cout << x << endl;
	//cout << rx << endl;
	// 交換變量的測(cè)試
	int a = 3, b = 4;
	swap(a, b);
	assert(a == 4 && b == 3);
	a = 3, b = 4;
	swap2(&a, &b);
	assert(a == 4 && b == 3);
    return 0;
}

補(bǔ)充:(Effective C++)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-460629.html

  1. 對(duì)內(nèi)置基礎(chǔ)類型,傳值更高效;
  2. 對(duì)OO面向?qū)ο笾凶远x的類型而言,在函數(shù)中傳遞const引用更高效。

到了這里,關(guān)于C++的指針和引用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • C++【4】指針與引用;數(shù)組指針;指針數(shù)組

    /* ?? ?指針變量作為函數(shù)參數(shù) ?? ??? ?函數(shù)的參數(shù)可以是指針類型,它的作用是將一個(gè)變量的地址傳送到另一個(gè)函數(shù)中。 ?? ??? ?指針變量作為函數(shù)參數(shù)與變量本身作為函數(shù)參數(shù)不同,變量作函數(shù)參數(shù)傳遞的是具體值。 ?? ??? ?而指針作為函數(shù)參數(shù)傳遞的是內(nèi)存的地址

    2024年02月07日
    瀏覽(18)
  • C++的指針和引用

    C++中內(nèi)存單元內(nèi)容和地址 內(nèi)存由很多的內(nèi)存單元組成,這些內(nèi)存單元用于存放各種類型數(shù)據(jù); 計(jì)算機(jī)對(duì)內(nèi)存的每個(gè)內(nèi)存單元都進(jìn)行了編號(hào),這個(gè)編號(hào)就稱為內(nèi)存地址,地址決定了內(nèi)存單元在內(nèi)存中的位置; 記住這些內(nèi)存單元地址不方便,因此C++語(yǔ)言的編譯器讓我們通過(guò)名字

    2024年02月06日
    瀏覽(20)
  • 【C++】引用與指針

    【C++】引用與指針

    專欄放在【 C++知識(shí)總結(jié) 】,會(huì)持續(xù)更新,期待支持 ?? 引用的概念 在C++中,引用的本質(zhì)其實(shí)就是給一個(gè)已經(jīng)存在的變量 ”起別名“ 。也就是說(shuō), 引用與它所引用的對(duì)象共用一塊空間 。( 同一塊空間的多個(gè)名字 ) 就比如說(shuō),李逵又叫黑旋風(fēng),而黑旋風(fēng)就是指李逵本人,只

    2024年02月02日
    瀏覽(22)
  • c++的引用和指針

    c++的引用和指針

    我們要清楚的知道,使用指針和引用都可以的傳入函數(shù)的main函數(shù)的變量在局部函數(shù)改變值時(shí),main函數(shù)里面相應(yīng)的變量也會(huì)改變值。但他倆的方式不同。 我們先來(lái)說(shuō)指針,指針傳入局部參數(shù)時(shí),他會(huì)在創(chuàng)建個(gè)局部指針變量,然后把傳入的地址賦值給局部的指針變量,然后修改

    2024年02月09日
    瀏覽(26)
  • C++[第五章]--指針和引用

    引用就是別名,引用定義時(shí)必須初始化: int a; int b=a; //b即為a的別名 如果不是形參,必須初始化,引用某一變量 指針和c一樣; this指針 在類的成員函數(shù)中使用,表示當(dāng)前對(duì)象; C++11 新增了一種引用 類型 引用名 = 右值表達(dá)式; 引入右值引用如: 編譯器允許我們?yōu)?num 左值建立

    2024年02月15日
    瀏覽(24)
  • C++拾遺(四)引用與指針

    引用和指針是兩種不同的概念,盡管它們?cè)谀承┓矫嬗幸恍┫嗨浦?,但它們?cè)诠δ芎陀猛旧鲜怯兴鶇^(qū)別 引用:引用是別名,是對(duì)已存在變量的另一個(gè)稱呼,一旦一個(gè)變量被引用,就不能再被引用其他變 量。 int a = 10; int ref = a; ? 這里, ref ?是? a ?的引用,它們引用的是同

    2024年01月25日
    瀏覽(21)
  • 【C++初階(三)】引用詳解(對(duì)比指針)

    【C++初階(三)】引用詳解(對(duì)比指針)

    ??博主CSDN主頁(yè):杭電碼農(nóng)-NEO?? ? ?專欄分類:C++初階之路? ? ??代碼倉(cāng)庫(kù):NEO的學(xué)習(xí)日記?? ? ??關(guān)注我??帶你學(xué)習(xí)排序知識(shí) ? ???? C語(yǔ)言中有一利器: 指針 而C++中增加了另一利器: 引用 這兩個(gè)板塊的存在 極大了提升了C/C++的可用性! 本篇文章將給大家詳細(xì)講解引用 并

    2024年02月12日
    瀏覽(28)
  • C++中const,指針和引用

    在線C/C++編譯器,可以試著運(yùn)行代碼。 在C語(yǔ)言中,const修飾的量稱為 常變量 (在編譯過(guò)程中,const就是當(dāng)成變量的編譯生成指令的),不可以直接修改它的值,但是可以 通過(guò)地址進(jìn)行修改其對(duì)應(yīng)的值 。并且const修飾的變量可以不進(jìn)行初始化,編譯器最后默認(rèn)賦值為0。 然而在

    2024年02月13日
    瀏覽(25)
  • C++中的引用及指針變量

    目錄 1.1 C++中的引用 1.2 C++中的指針變量(pointer) 1.1 C++中的引用 C++中的引用(reference)是一種特殊的變量,它是某個(gè)已存在變量的另一個(gè)名字。引用變量與指針變量類似,但引用變量必須在聲明時(shí)進(jìn)行初始化,并且一旦引用變量與某個(gè)變量關(guān)聯(lián)起來(lái),就無(wú)法再與其他變量關(guān)

    2024年01月20日
    瀏覽(26)
  • 【C++那些事兒】函數(shù)重載與C++中的“指針“——引用

    【C++那些事兒】函數(shù)重載與C++中的“指針“——引用

    君兮_的個(gè)人主頁(yè) 即使走的再遠(yuǎn),也勿忘啟程時(shí)的初心 C/C++ 游戲開(kāi)發(fā) Hello,米娜桑們,這里是君兮_,我之前看過(guò)一套書(shū)叫做《明朝那些事兒》,把本來(lái)枯燥的歷史講的生動(dòng)有趣。而C++作為一門接近底層的語(yǔ)言,無(wú)疑是抽象且難度頗深的。我希望能努力把抽象繁多的知識(shí)講的生

    2024年02月08日
    瀏覽(29)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包