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è)
- 關(guān)于const修飾的部分
#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)
- 從現(xiàn)代編程語(yǔ)言角度,使用堆或者說(shuō)使用動(dòng)態(tài)內(nèi)存分配,是一件很自然的事情
- 動(dòng)態(tài)分配內(nèi)存帶來(lái)了不確定性:內(nèi)存分配耗時(shí)?失敗怎么辦?
- 一般而言,當(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)分析智能指針
- 應(yīng)用場(chǎng)景: 對(duì)象所有權(quán) 生命周期
- 性能分析
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++的引用
引用是什么?變量的別名,是一種特殊的指針,不允許修改的指針。
使用指針有哪些坑:
- 空指針
- 野指針
- 不知不覺(jué)改變了指針的值,卻繼續(xù)使用
使用引用則可以:
- 不存在空引用
- 必須初始化
- 一個(gè)引用永遠(yuǎn)指向它的初始化的那個(gè)對(duì)象
- 基本使用:可以認(rèn)為是變量的別名,使用時(shí)候可以認(rèn)為是變量本身
有了指針為什么還要有引用?
為了支持運(yùn)算符重載。
有了引用為什么還需要指針?
為了兼容C語(yǔ)言。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-460629.html
#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
- 對(duì)內(nèi)置基礎(chǔ)類型,傳值更高效;
- 對(duì)OO面向?qū)ο笾凶远x的類型而言,在函數(shù)中傳遞const引用更高效。
到了這里,關(guān)于C++的指針和引用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!