zoukankan      html  css  js  c++  java
  • ###学习《C++ Primer》- 5

    点击查看Evernote原文

    // @author:       gr
    // @date:         2014-10-20
    // @email:        forgerui@gmail.com
    

    Part 5: 动态内存(第12章)

    一、new初始化对象

    使用new 对类类型和内置类型进行初始化会有不同的效果。对于类类型,不论采用何种形式,对象都会使用默认构造函数来初始化。直接初始化的内置类型对象值被良好定义,而默认初始化的对象的值是未定义的。

    // 类型后没括号是默认初始化,有括号是直接初始化
    string *ps1 = new string;   //值初始为空string
    string *ps2 = new string(); //值初始为空string
    int *pi1 = new int;         //值未定义
    int *pi2 = new int();       //值初始为0
    

    往往,对动态分配的对象进行直接初始化通常是个好主意。

    可以使用auto来自动推断我们想要分配的类型。要求,括号中仅有单一初始化器时才可以使用auto

    // p指向一个与obj类型相同的对象,该对象用obj进行初始化
    auto p1 = new auto(obj);
    // 错误,括号中只能有一个初始化器
    auto p2 = new auto{a, b, c};
    

    p1的类型是一个指针,从obj自动推断出来。如果obj是一个int,那么p1就是个int*

    二、动态分配的const对象

    由于分配的对象是const的,所以new返回的指针是一个指向const的指针。初始化规则和上面new初始化一样,如果是内置类型,则需要显示初始化。

    const int* pi = new const int(1024);        //显示初始化
    const string* ps = new const string;        //隐示初始化
    

    三、内存耗尽

    如果使用new无法分配所要求的空间,这时会抛出一个bad_alloc的异常。可以通过改变使用new的方式来阻止抛出异常:

    int* pi1 = new int(1);                  //如果分配失败,抛出std::bad_alloc异常
    int* pi2 = new (nothrow) int(1);        //如果分配失败,new返回一个空指针,不抛出异常
    

    这种new称为定位new,允许向new传递参数。在本例中,将nothrow传递给new
    bad_allocnothrow都在头文件new,记着要#include <new>

    四、delete

    delete工作:

    1. 销毁给定指针指向的对象
    2. 释放对应的内存

    传递给delete的指针必须指向动态分配的内存,或是一个空指针。不能对同一块内存释放两次
    const对象虽然是不可改变的,但是可以销毁的,和其他的销毁一样,如下:

    const int* pi = new const int(1);
    delete pi;
    

    在delete指针过后,要重置为nullptr。这样以后进行NULL检查才会有作用。

    delete p;
    p = nullptr;
    

    但即使这样,也不能保证所有指针都置为nullptr

    int *p(new int(42));
    auto q = p;
    delete p;
    p = nullptr;
    

    虽然把p置为nullptr,q仍为无效的。

    五、shared_ptr类

    shared_ptr在头文件memory中。使用它,记着#include <memory>
    vector类似,智能指针也是模板,在尖括号内给出类型。智能指针使用方式与普通方式类似,解引用一个智能指针返回它指向的对象。

    shared_ptr<string> p1;
    p1->empty();        // 调用成员函数
    shared_ptr<vector<string> > pv;
    

    使用make_shared函数,创建智能指针。

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

    当指向一个对象的最后一个shared_ptr被销毁时,即引用计数为0时,shared_ptr类会自动销毁此对象。无需手动调用。

    六、shared_ptr和new结合使用

    如果不初始化智能指针,它就会被初始化为一个空指针。还可以用new返回的指针来初始化智能指针。只能使用显示转换,不能使用隐式转换:

    shared_ptr<int> pi1 = new int(11);      //错误,隐匿转换
    shared_ptr<int> pi2(new int(11));     //正确,显示转换
    

    七、unique_ptr

    shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定对象。它不支持普通的拷贝或赋值操作。

    unique_ptr<string> p1(new string("dfss"));
    unique_ptr<string> p2(p1);          //错误,不支持拷贝
    unique_ptr<string> p3;
    p3 = p1;                            //错误,不支持赋值
    

    但可以通过调用releasereset将指针的所有权从一个unique_ptr转移给另一个unique

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

    虽然标准库中auto_ptr仍然存在,但使用它会有许多隐患,所以尽量不要使用。

    八、weak_ptr

    weak_ptr不控制所指向对象生存期的智能指针,它指向一个由shared_ptr管理的对象。一旦最后一个指向对象的shared_ptr被销毁,即使有weak_ptr指向这个对象,对象也还是会被释放。这就是weak的体现。

    auto p = make_shared<int>(42);
    weak_ptr<int> wp(p);
    

    由于对象可能不存在,我们不能使用weak_ptr直接访问对象,而必须调用lock。此函数检查weak_ptr是否仍存在,存在返回一个指向共享对象的shared_ptr。

    if (shared_ptr<int> np = wp.lock()){ //如果np不为空则条件成立
        // 在if中,np与p共享对象
    }
  • 相关阅读:
    JAVA基础-抽象类和接口
    JAVA基础-多态
    JAVA基础-继承机制
    C++(二十七) — 深拷贝、浅拷贝、复制构造函数举例
    C++(二十六) — 构造函数、析构函数、对象数组、复制构造函数
    C++(二十五) — 类的封装、实现、设计
    C++(二十四) — 指向字符的指针为什么可以用字符串来初始化,而不是字符地址?
    C++(二十三) — 内存泄漏及指针悬挂
    C++(二十二) — 指针变量、函数指针、void指针
    C++(二十一) — 引用概念及本质
  • 原文地址:https://www.cnblogs.com/gr-nick/p/4128717.html
Copyright © 2011-2022 走看看