C++----动态内存

来源:互联网 发布:magnet 磁链下载 软件 编辑:程序博客网 时间:2024/05/29 10:12

除了自动和static对象外,C++还支持动态分配内存对象。动态分配的对象的生存期与它们在哪里创建时无关的,只有当显示地被释放时,这些对象才会销毁。
动态对象的正确释放被证明是编程中及其容易出错的地方。为了更安全地使用动态对象,标准库定义了两个智能指针类型来管理动态分配的对象。当一个对象应该被释放时,指向它的智能指针可以确保自动地释放它。
为了更容易(同时也更安全)地使用动态内存,新的标准库提供了两种智能指针(smart pointer)类型来管理动态对象。新标准库提供的这两种智能指针的区别在于管理低层指针的方式:
shared_ptr允许多个指针指向同一个对象;unique_ptr则“独占”所指向的对象。标准库还定义了一个名为weak_ptr的伴随类。它是一种弱引用,指向shared_ptr所管理的对象。这三种类型都定义在memory头文件中。

shared_ptr类

make_shared函数

最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准库函数。此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。

//指向一个值为42的int的shared_ptrshared_ptr<int> p3 = make_shared<int>(42);//指向一个值为“9999999999”的stringshared_ptr<string> p4 = make_shared<string>(10,'9');//p5指向一个值初始化的int,即,值为0shared_ptr<int> p5 = make_shared<int>();

shared_ptr的拷贝和赋值

当进行拷贝或赋值操作时,每个shared_ptr都会记录有多少个其他shared_ptr指向相同的对象:

auto p = make_shared<int>(42);//p指向的对象只有一个引用者auto q(p);//pq指向相同对象,次对象有两个引用者

我们可以认为每个shared_ptr都有一个关联的计数器,通常称其为引用计数(reference count)。无论何时我们拷贝一个shared_ptr,计数器都会递增。当我们给shared_ptr赋予一个新值或是shared_ptr被销毁(例如一个局部的shared_ptr离开作用域)时,计数器就会递减。
一旦一个shared_ptr的计数器变为0,它就会自动释放自己所管理的对象。

直接管理内存

C++语言定义了两个元素符来分配和释放动态内存。运算符new分配内存,delete释放new分配额内存。
如果我们提供了一个括号包围的初始化器,就可以使用auto从此初始化器来推断我们想要分配的对象的类型。但是,由于编译器要用初始化器类型来推断要分配的类型,只有当括号中仅有单一初始化器时才可以使用auto。

auto p1 = new auto(obj);//p指向一个与obj类型相同的对象auto p1 = new auto{a,b,c};//错误

动态分配的const对象

用new分配const对象是合法的:

//分配并初始化一个const intconst int *pci = new const int(1024);//分配并默认初始化一个const的空stringconst string *pcs = new cosnt string;

类似其他任何const对象,一个动态分配的const对象必须进行初始化。对于一个定义了默认构造函数的类类型,其const动态对象可以隐式初始化,而其他类型的对象就必须显示初始化。

释放动态内容

delete p;

销毁给定的指针指向的对象、释放对应的内存。

unique_ptr

与shared_ptr不同,某个时刻智能有一个unique_ptr指向一个给定对象。当unique_ptr被销毁时,它所是想的对象也被销毁。与shared_ptr不同,没有类似make_shared的标准库函数返回一个unique_ptr。当我们定义一个unique_ptr时,需要将其绑定到一个new返回的指针上。类似shared_ptr,初始化unique_ptr必须采用直接初始化形式:

unique_ptr<double> p1;//可以指向一个double的unique_ptrunique_ptr<int> p2(new int(42));

由于一个unique_ptr拥有它指向的对象,因此unique_ptr不支持普通的拷贝或赋值操作:

unique_ptr<string> p1(new string("Stedasdas"));unique_ptr<string> p2(p1);// wrong;unique_ptr<string> p3;p3 = p2;//wrong

但是可以:

unique_ptr<string> p2(p1.release());//realse将p1置为空,所有权转移给p2unique_ptr<string> p3(new string("Trex"));p2.reset(p3.release());//reset释放了p2原来指向的内存,所有权给p2

reset参数可选,没有就释放原本的内存。

weak_ptr

指向由shared_ptr管理的对象,但是不增加引用数。

原创粉丝点击