1 对于局部自动对象,当我们进入其定义所在的程序块时被创建,在离开块时销魂。局部static对象在第一次使用前分配,在程序结束时销魂。除了这些外,C++还支持动态分配内存对象。动态分配对象的生存期与它们在哪里创建无关,只有当显示释放时,这些对象才会被销毁;
2 new在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象进行初始化;delete接受一个动态对象的指针,销毁该对象,并释放与之关联的内存;
3 shared_ptr允许多个指针指向同一个对象;unique_ptr则独占所指向的对象。标准库还定义了一个名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象;
4 最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准库函数,此函数在动态内存中分配一个对象并初始化它;
5 shared_ptr的析构函数会递减它所指向的对象的引用计数。如果引用计数变为0,shared_ptr的析构函数会销毁对象,并释放它占用的内存。
6 当我们拷贝一个vector时,原vector和副本vector中元素是相互分离的;使用动态内存的一个常见原因是允许多个对象共享相同的状态;
7 delete p; //p必须指向一个动态分配的对象或者一个空指针;
8 由内置指针(而不是智能指针)管理的动态内存在被显示释放前一直都会存在;
9 用new返回的指针来初始化智能指针:接受指针参数的智能指针构造函数是explicit的,不能将一个内置指针隐式转换为一个智能指针。
Shared_ptr<int> p1=new int(1024); //错误,必须使用直接初始化形式
Shared_ptr<int> p2(new int(1024));
10 智能指针陷阱
不使用相同的内置指针值初始化多个智能指针;
不delete get()返回的指针;
不使用get()初始化或reset另一个智能指针;
如果你使用get()返回的指针,当一个对象的智能指针销毁后,你的指针就变得无效了;
如果使用智能指针管理的资源不是new分配的内存,记得传递给它一个删除器;
11 unique_ptr拥有它指向的对象。每个时刻只能有一个unique_ptr指向一个给定的对象,当指针被销毁时,指向的对象也被销魂;
12 由于unique_ptr独占拥有它指向的对象,所以它不支持拷贝或赋值操作;虽然我们不能赋值或拷贝unique_ptr,但可以通过调用release或reset将指针所有权从一个unqiue_ptr转移给另一个unique;
13 weak_ptr是一种不可控所指向对象生存期的智能指针,它指向一个shared_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放;
由于对象可能不存在,不能使用weak_ptr直接访问对象,而必须调用lock
weak_ptr<string> wp(p);
if(shared_ptr<string> np=wp.lock()){
//dosomething
}
应用:
#include <vector>
#include <iostream>
using namespace std;
class StrBlob{
public:
typedef vector<string>::size_type size_type;
StrBlob();
StrBlob(initializer_list<string> li);
size_type size() const { return data->size();}
bool empty() const { return data->empty();}
void push_back(const string &t){data->push_back(t);}
void pop_back();
string& front();
string& back();
string& deref() const;
StrBlob& incr();
private:
size_t curr;
shared_ptr<vector<string>> data;
weak_ptr<vector<string>>wptr;
shared_ptr<vector<string>> check(size_type i, const string &msg) const;
};
StrBlob::StrBlob() : data(make_shared<vector<string>>()) {
}
StrBlob::StrBlob(initializer_list<string> li):data(make_shared<vector<string>>()){}
shared_ptr<vector<string>> StrBlob::check(StrBlob::size_type i, const std::string &msg) const {
auto ret=wptr.lock();
if(ret){
if(i>=ret->size()){
throw out_of_range(msg);
}
return ret;
}
}
string& StrBlob::front() {
check(0,"front on empty StrBlob");
return data->front();
}
void StrBlob::pop_back() {
check(0,"pop_back on empty StrBlob");
data->pop_back();
}
string& StrBlob::deref() const {
auto p=check(curr,"dereference past end");
return (*p)[curr];
}
StrBlob& StrBlob::incr() {
check(curr,"increment past end");
++curr;
return *this;
}