指针定义的基本形式:指针本身就是一个变量,其符合变量定义的基本形式,它存储的是值的地址。对类型T,T是“到T的指针”类型,一个类型为T的变量能保存一个类型T的对象的地址。
如:
int a=112; float c=3.14; int* d=&a; float* e=&c; cout << d << endl; cout << e << endl; cout << (*d) << endl; cout << (*e) << endl;
通过一个指针访问它所指向地址的过程称为间接访问(indirection)或者引用指针(dereferencing the point);这个用于执行间接访问的操作符是单目操作符*:
cout<<(*d)<<endl; cout<<(*e)<< endl;
概念:
具体分析:
比如:a=b+c; &a是允许的操作,而&(b+c)不能通过编译,因此a是一个左值,而(b+c)是一个右值;
指针的数组(array of pointers)与数组的指针(a pointer to an array):
int* a[4]; // array of pointers 指针的数组 int (*b) [4]; // a pointer to an array 数组的指针 // 输出 cout << *(a[0]) << endl; cout << (*b)[0] << endl;
const pointer与pointer to const例子:
char strHelloworld[]={"helloworld"}; char const * pStr1="helloworld"; //和const char* pStr1等效 char * const pStr2="helloworld"; char const * const pStr3="helloworld"; pStr1=strHelloworld; //pStr2=strHelloworld; //pStr2不可改 //pStr3=strHelloworld; //pStr3不可改
关于const修饰的部分:
指向指针的指针例子:
int a=123; int* b=&a; int** c=&b;
*操作符具有从右向左的结合性,上面取值规则如下:
NULL指针:一个特殊的指针变量,表示不指同任何东西。
int* a=NULL;
NULL指针给了一种方法,来表示特定的指钍目前未指向任何东西,使用的注意事项:
内存泄漏问题:指程序中己动态分配的维内存由于某种原因程序未释放或无法释,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
内存泄漏发生原因和排查方式:
while (true) { int* wp1 = new int(10); //内存泄漏 }
C++中推出了四种常用的智能指针:
auto w = std::make_unique<int>(10); cout << *(w.get()) << endl; // 10 //auto w2 = w; // 编译错误如果想要把 w 复制给 w2, 是不可以的。 auto w2 = std::move(w); // w2 获得内存所有权,w 此时等于 nullptr cout << ((w.get() != nullptr) ? (*w.get()) : -1) << endl; // -1 cout << ((w2.get() != nullptr) ? (*w2.get()) : -1) << endl; // 10
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 // move 语法,意味着放弃了对内存的所有权和管理 auto wAA = std::make_shared<int>(30); auto wAA2 = std::move(wAA); // 此时 wAA 等于 nullptr,wAA2.use_count() 等于 1 cout << ((wAA.get() != nullptr) ? (*wAA.get()) : -1) << endl; // -1 ccout << wAA.use_count() << endl; // 0 cout << wAA2.use_count() << endl; // 1
struct AW { shared_ptr<BW> pb; ~AW() { cout << "~AW()" << endl; } }; struct BW { weak_ptr<AW> pa; //此处改为shared_ptr则会发生内存泄漏(循环引用) ~BW() { cout << "~BW()" << endl; } }; void Test() { cout << "Test shared_ptr and shared_ptr: " << endl; shared_ptr<A> tA(new A()); shared_ptr<B> tB(new B()); cout << tA.use_count() << endl; // 1 cout << tB.use_count() << endl; // 1 tA->pb = tB; tB->pa = tA; cout << tA.use_count() << endl; // 2 cout << tB.use_count() << endl; // 2 } void Test() { 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(); return 0; }
C++的引用是一种特殊的指针,不允许修改的指针,参考 C++:引用的简单理解 。
注:C++中类的引用也需要显式定义,C#中除了值类型则全是引用类型,注意区别。
使用指针有空指针、野指针、不知不觉改变了指针的值却继续使用的问题,使用引用则:
int x = 1, x2 = 3; int& rx = x; rx = 2; cout << x << endl; //2 cout << rx << endl; //2 rx = x2; cout << x << endl; //3 cout << rx << endl; //3
有了指针为什么还需要引用?
Bjarne Stroustrup的解释:为了支持函数运算符重载;
有了引用为什么还需要指针?
Bjarne Stroustrup的解释:为了兼容C语言;
关于函数传递参数类型的说明: