一.c++指针与引用
1.1指针的概念
内存是由很多内存单元组成,而计算机对内存的每个内存单元都进行编号,而这个编号就是内存地址.而记住这些这么多地址的内容是极其不便的.于是指针的概念就出现了.通过指针的方式可以将这些指针与内存地址相绑定.从而减轻程序员的压力.
1.2 指针的定义
指针的基本形式:指针本身就是一个变量.它存储的是值的地址.对类型T,T是“到T的指针”类型, 一个类型为T的变量能保存一个类型T的对象的地址.而&X**代表着这个X值的地址.
例如
int a = 1;float b= 3.14;
int *c =&a; float *d = &b;
1.3 数组指针与指针数组
定义:
数组指针(array of pointers)与指针数组(a pointer to an array)
int c[4] = { 1,2,3,4 };
int *f;
int *a[4];
int(*b)[4];
f = c;
b = &c;
for ( unsigned int i = 0; i < 4; i++)
{
a[i] = &(c[i]);
}
cout << "address of c :" << c << " value of f :" << c[1] << endl;
cout << "address of f :" <<f <<" value of f :"<< *(f+1) << endl;
cout << "address of b :" << b << " value of f :" << (*b)[1] << endl;
cout << "address of a :" << a << " value of f :" << *a[1] << endl;
return 0;
1.4 const与指针
cost pointer 与 pointer to const
char strHelloworld[] = { "helloworld" };
char const *pStr1 = "helloworld";
char * const pStr2 = strHelloworld;
char const * const pStr3 = "helloworld";
pStr1 = strHelloworld;
//pStr2 = strHelloworld //pStr2不可改
//pStr3 = strHelloworld //pStr3不可改
int j = strnlen_s(strHelloworld, MAX_VALUE);
cout << "const *pStr1: " << *pStr1 << endl;
cout << "* const pStr2: " << *pStr2 << endl;
cout << "const * const pStr3: " << *pStr3 << endl;
for (int i = 0; i < j; i++){
pStr2[i] += 1;
}
cout << "const *pStr1: " << *pStr1 << endl;
cout << "* const pStr2: " << *pStr2 << endl;
cout << "const * const pStr3: " << *pStr3 << endl;
const修饰的部分
1.看左侧最近的部分
2.如果左侧没有,则看右侧
1.5 cpp程序在存储区域划分
int a = 0; //(GVAR全局初始区)
int *p1; //(bss)全局未初始化区
int main() //(text)代码区
{
int b; //(stack)栈区变量
char s[] = "abc"; //(stack)栈区变量
int *p2; //(stack)栈区变量
char *p3 = "123";//123\0在常量区,p3在(stack)栈区
static int c = 0; //(GVAR)全局(静态)初始化区
p1 = new int(10); //(heap)堆区变量
p2 = new int(20); //(heap)堆区变量
char *p4 = new char[9];//(heap)堆区变量
return 0; //(text)代码区
}
1.6 内存泄漏
- 内存泄漏问题:指程序中已分配的堆内存因某种原因无法释放或未释放.从而导致系统内存的浪费
- 内存泄漏发生的原因: 配置内存后,所有该内存的指针都遗失.由于缺乏垃圾回收机制,故需要工程人员进行释放.
- 内存泄漏排除方式: 只能在程序运行过程中,进行判别和诊断.
1.6.1 使用比指针更安全的方案
1.6.1.1使用更安全的指针 -> 智能指针
1.auto_ptr指针
在auto_ptr 对象销毁时,它所管理的对象也会自动被delete掉
所有权转移:当它不小心传递给另外的智能指针时,原来的指针就不再拥有该对象.所以在拷贝和赋值过程中.会直接剥夺该指针对原对象内存的控制权.从而将该指针 指向nullptr
//auto_ptr声明 和赋值
auto_ptr<int> pt(new int(10));
auto_ptr<int> ps = pt;
//由于赋值后会导致原智能指针为nullptr是由于对=进行重载
auto_ptr& operator=(auto_ptr& _Right) noexcept
{ // assign compatible _Right (assume pointer)
reset(_Right.release());
return (*this);
}
2.unique_ptr
这种指针是专属所有权,所以它只能被一个对象持有,不支持赋值和复制.但是如果需要转移所有权可调用move进行控制权的转移
//unique_ptr定义
auto w = std::make_unique<int>(10);
cout << *(w.get()) << endl;
auto w1 = std::move(w);
cout << ((w.get() != nullptr) ? (*w.get()) : -1) << endl;
cout << ((w1.get() != nullptr) ? (*w1.get()) : -1 )<< endl;
3.shared_ptr与weak_ptr
shared_ptr通过一个引用计数共享一个对象
当引用计数为0时,该对象没有被使用,可以进行析构
于是会出现循环引用,导致两个指针相互指向 从而引用数无法清零,造成内存泄漏。
于是乎 出现了weak_ptr, 作用是协助shared_ptr工作,可获得资源的观测权,意味着weak_ptr只对shared_ptr进行引用,而不改变引用计数, 当shared_ptr失效后,其weak_ptr也失效
//ahared_ptr定义
auto w = shared_ptr<int>(new int(20));
cout << *(w.get()) << endl;
cout << w.use_count << endl;
1.6.1.2.不使用指针,使用更加安全的方式 -> 引用
引用: 是一种特殊的指针,不允许修改的指针
而常见的指针的遗漏点:
1.空指针
2.野指针
3.不知什么时候修改了 指针的值.
而引用则可以:
1.不存在空引用
2.必须初始化
3.一个引用永远指向他初始化的对象
int j = 3;
int &s = j;
cout << s << endl;