野指针与智能指针
- 野指针指向了非法的内存区域,
- 典型的情况
- 动态申请之后又释放的内存
- 临时变量自动消亡之后原先的那块地址。
- 错误的指针运算
- 强制的指针类型转换
- 智能指针模板类
- 一些动态分配的内存可能内存泄漏:1.可能忘记delete了 2.函数内部抛出了异常没有执行到delete语句。
- 智能指针的思想是,将指针包装成一个对象;当指针析构时,在析构函数里释放所指向的内存空间。
- 常见的智能指针模板有
auto_ptr(被c++11弃用), unique_ptr, shared_ptr, weak_ptr
- 将new出来的地址赋值给智能指针,不需要人为delete,当智能指针析构时会自动delete。
- 智能指针模板包含在头文件 <memory> 中。
- 智能指针基本操作:
- 智能指针类接受指针作为(显式)构造函数参数,不能直接用指针赋值(也就是不能隐式类型转换)
shared_ptr<int> p(new int(3)); \\ok
p = new int(3)\\wrong
- 智能指针对象可以:*解引用,->访问结构成员,赋值给兼容的指针变量,赋值给同类型智能指针。
- 智能指针构造的参数必须要是堆内存(即动态分配出来的),否则析构时引起错误。
- 智能指针类接受指针作为(显式)构造函数参数,不能直接用指针赋值(也就是不能隐式类型转换)
- 如何避免多次delete同一个内存位置?
- 考虑这样的问题,下面的代码析构时是否会delete同一个内存两次
为了解决这个问题,智能指针有两种策略:auto_ptr<string> ps (new string ("hello world")); auto_ptr<string> p = ps;
- 建立 所有权 概念(auto_ptr, unique_ptr这样做),对于特定的对象,只能被一个智能指针对象拥有;智能指针的赋值操作会转让所有权。
- 所有权被转让之后,就不能通过这个智能指针去访问对象。
auto_ptr<string> p (new string ("hello world")); auto_ptr<string> q = p; // p loses ownership cout << *p << endl; // segmentation fault, 引用空指针
- unique_ptr与auto_ptr的区别:上面的代码如果使用unique_ptr,第二行就无法通过编译。这个意义上,unique_ptr更安全。
- 但是unique_ptr允许通过函数返回值来赋值,因为这里源智能指针是个右值。
unique_ptr<string> func(const char* s){ unique_ptr<string> temp (new string (s)); return temp; } unique_ptr<string> p = func("Allowed uniquely"); // ok p = unique_ptr<string>(new string("hello world")) // ok unique_ptr<string> q = move(p); // ok, 使用了move得到右值引用
- 引用计数(shared_ptr这样做),维护这块内存被多少智能指针引用,只有最后一个对象析构时才会delete。
- 如果希望指针用于数组,unique_ptr提供这样的方式,而shared_ptr, auto_ptr都不提供。这样创建的指针析构时会使用delete[]。
std::unique_ptr<double []> p (new double[5]);