C++---CHAPTER 12 : Dynamic Memory

静态内存、栈内存、动态内存

  • 静态内存:保存局部static对象;类static对象、已经定义在任何函数之外的变量。
  • 栈内存:保存定义在函数内的非static对象;

其中栈对象仅在其定义的程序块运行时才存在;static对象在使用之前分配,程序结束时销毁。

  • 内存池(称为堆heap):存储动态分配的对象,即在程序运行时分配的对象,动态内存不在使用时,代码必须显式地销毁它们。

提出智能指针:为了防止意外发生,针对newdelete处理失误的情况;

  • 智能指针(smart pointer):定于在memory头文件中,有shared_ptrunique_ptr;伴随类weak_ptr表示的弱引用。

shared_ptr

shared_ptr<string> p1; //可以指向string
shared_ptr<list<int>> p2;
//如果p1不为空,检查它是否指向一个空string
if(p1 && p1->empty())
  *p1 = "hi"; //如果p1指向一个空string,解引用p1,将一个新值赋予string
  • make_shared函数
    使用时必须指定想要创建的对象的类型:
shared_ptr<int> p3 = make_shared<int>(42);
//p4指向一个值为"999999999"的string
shared_ptr<string> p4 = make_shared<string>(10,'9');
//p5指向值初始为0的int
shared_ptr<int> p5 = make_shared<string>();

通常使用auto

auto p6 = make_shared<vector<string>>();

拷贝和赋值

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

可以认为被一个shared_ptr都关联一个引用计数,一旦计数器的值变为0,它就会自动释放自己所管理的对象:

auto r = make_shared<int>(42); //r指向的int只有一个引用者
r = q; //给r赋值,令它指向另一个地址;
          // 递增q指向的对象的引用计数;
    //   递减r原来指向的对象的引用计数;
  //r原来指向的对象已没有引用者,会自动释放;

下面的例子展示了使用动态内存的一个常见的原因是允许多个对象共享相同的状态:

Blob<string> b1; //空Blob
{
    Blob<string> b2 = {"a"};
    b1 = b2; //b1与b2共享相同的元素,b2被销毁了,但b2中的元素不能销毁;b1指向由最初b2创建的元素;
}

练习12-2:定义自己的const函数:

//
// Created by zc on 2019-08-21.
//

#include<iostream>
#include<vector>
#include<memory>
using namespace std;

class StrBlob
{
public:
    typedef vector<string>::size_type size_type;
    StrBlob();
    StrBlob(initializer_list<string> il);
    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& front() const;
    string& back() const;
private:
    shared_ptr<vector<string>> data;
    void check(size_type i, const std::string &msg) const;

};

StrBlob::StrBlob() : data(make_shared<vector<string>>()) {}
StrBlob::StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)){}
//检查是否越界
void StrBlob::check(size_type i, const string &msg) const
{
    if (i >= data->size())
        throw out_of_range(msg);
}

string& StrBlob::front()
{
    check(0, "front on empty StrBlob");
    return data->front();
}

string& StrBlob::back()
{
    check(0,"back on empty StrBlob");
    return data->back();
}

//练习12-2
//目的:非常量函数不能够调用常量对象
string& StrBlob::front() const
{
    check(0, "front on empty StrBlob");
    return data->front();
}
string& StrBlob::back() const
{
    check(0, "front on empty StrBlob");
    return data->back();
}
void StrBlob::pop_back()
{
    check(0, "pop_back on empty StrBlob");
    data->pop_back();
}



//test
int main()
{
    const StrBlob csb{"hello", "world", "zhengchu"};
    StrBlob sb{"hello", "world", "jojo"};
    std::cout<< csb.front() << " " << csb.back() << endl;
    sb.back() = "dio";
    cout<< sb.front() << " " << sb.back() << endl;
    return 0;
}

hello zhengchu
hello dio

12-3:需要为上面的类添加const版本的push_backpop_back
参考:https://www.douban.com/group/topic/61573279/

Ans:
可以用的原因,因为修改的不是指针,而是指针指向的数据,因此完全可以用const指针。
不可以用的原因:虽然在类的具体实现中,数据成员是一个指向vector的智能指针;但由于类的封装,在类的使用者看来,数据成员是vector,他们并不知道具体的实现使用了智能指针。那么当类的使用者声明类的常量对象时,他们期待的结果是vector的内容不会被改变。所以我们在设计这个类的时候,要考虑到类的使用者的真实意图,对于像push_back和pop_back这样会改变智能指针所指向的vector内容的成员函数,我们不应该声明和定义成const版本。这样在类的使用者使用类的常对象时,就不能调用push_back和pop_back成员函数,不能改变智能指针所指向的vector的内容了,这正好与类的使用者的意图相符。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容