C++动态内存使用

来源:互联网 发布:平面设计用什么软件 编辑:程序博客网 时间:2024/05/15 06:40

在C++中,直接对动态内存的管理是通过运算符newdelete来完成的。

  • new:在动态内存中为对象分配空间并返回一个指向该对象的指针。
  • delete: 接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。

一、使用new动态分配和初始化对象的几种方式:

1. 默认情况下,动态分配的对象是默认初始化的,故内置类型或组合类型的对象的值是未定义的,类类型对象将用默认构造函数进行初始化

int *pi = new int;  //pi指向一个动态分配的,未初始化的无名对象string *ps = new string;    //初始化为空string

2. 使用直接初始化方式来初始化一个动态对象,可以使用传统的构造方式(使用括号),在新标准下,也可以使用列表初始化(使用花括号)

int *pi = new int(1024);string *ps = new string(10, '9');vector<int> *pv = new vector<int>{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

3. 对动态对象进行值初始化,在类型名之后跟一对空括号,主要针对内置类型,对于类类型,不管是默认初始化或值初始化都是通过默认构造函数来初始化的

string *ps = new string;    //默认初始化为空stringstring *ps = new string();  //值初始化为空stringint *pi1 = new int;         //默认初始化,*pi1值未定义int *pi2 = new int();       //值初始化为0,*pi2为0;

4. 使用一个括号包围的单一初始化器,编译器用初始化器的类型推断要分配的类型

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

5. 动态分配const对象

const int *pci = new const int(1024); //const对象必须要初始化

二、delete指针:

传递给delete的指针必须指向动态分配的内存或是一个空指针,释放一块并非new分配的内存,或者将相同的指针释放多次,其行为是未定义的。

使用newdelete管理内存存在的常见问题:

  • 忘记delete内存,即内存泄漏,查找这种错误是非常困难的
  • 使用已经释放掉的对象,通过在释放内存后将指针置为空,有时可以检测出这种错误
  • 同一块内存释放多次,可能会出现意外的后果

三、智能指针

为了更容易(同时也安全)地使用动态内存,新的标准库提供了两种智能指针类型来管理动态对象。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。新标准库提供的这两种智能指针的区别在于管理底层指针的方式:shared_ptr 允许多个指针指向同一对象;unique_ptr 则“独占”所指向的对象。标准库还定义了一个名为 weak_ptr 的伴随类,它是一种弱引用,指向shared_ptr所管理的对象。

shared_ptr<string> p1;

这里写图片描述

智能指针也是模板,当创建一个智能指针时,必须提供额外的信息-指针可以指向的类型。

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

shared_ptr<int> p3 = make_shared<int>(42);

每一个shared_ptr都有一个关联的计数器,称为引用计数,用来记录有多少一个其他的share_ptr指向相同的对象,当指向一个对象的最后一个shared_ptr被销毁时,share_ptr类会通过另一个特殊的成员函数-析构函数自动销毁此对象。

四、allocator类
new缺乏一些灵活性,因为它组合了内存分配和对象构造,当分配一大块内存时,如果希望在这块内存上按需构造对象,即将内存分配和对象构造分离。allocator类提供了一种类型感知的内存分配方法,它分配的内存是原始的,未构造的。

allocator是一个模板,它根据给定的对象类型来确定恰当的内存大小和对齐位置

allocator<string> alloc;            //可分配string的aallocator对象auto const p = alloc.allocate(n);   //分配n个未初始化的string

这里写图片描述

allocator类还有两个伴随算法,可以在未初始化内存中创建对象:

这里写图片描述

注意:只能对构造了的元素进行destroy操作,元素被销毁后可以重新使用这部分内存,释放内存通过调用deallocate。

五、程序使用动态内存处于以下三种原因之一:

  • 程序不知道自己需要使用多少个对象;
  • 程序不知到所需的准确类型
  • 程序需要在多个对象间共享数据

容器类是处于第一种原因而使用动态内存的典型例子。

使用动态内存的一个常见原因是运行多个对象共享相同的状态。

0 0
原创粉丝点击