c++动态内存

1、静态内存和栈内存:静态内存用来保存局部static对象、类static数据成员以及定义在函数之外的变量;栈内存用来保存定义在函数之内的非static对象,分配在静态或栈内存中的对象由编译器自动创建和销毁;对于栈对象,仅在其定义的程序块运行时才存在;static对象在使用之前分配,在程序结束时销毁。

2、除了静态内存和栈内存,每个程序还有一个内存池。这部分空间被称为自由空间或堆。(程序用堆来存储动态分配的对象)。

3、new,在动态内存中为对象分配空间并返回一个指向该对象的指针,可以选择对其进行初始化;delete,接受一个动态对象的指针,销毁对象,并释放与之关联的内存。

4、三种类型指针:shared_ptr允许多个指针指向同一个对象;unique_ptr独占指向的对象。weak_ptr(伴随类),指向shared_ptr所管理的对象。(三种类型都定义在头文件memery中)。

shared_ptr<string> p1;//指向string
shared_ptr<list<int>>p2;//指向int的list

5、默认初始化的智能指针中保存着一个空指针,在一个条件判断中使用智能指针 ,效果就是检测它是否为空。

6、make_shared标准库函数:

shared_ptr<int> p3 = make_shared<int>(42);
shared_ptr<string> p4 = make_shared<string>(10,'9');
shared_ptr<int> p5 = make_shared<int>();
auto p6 = make_shared<vector<string>>();

7、每个sharedptr都有一个关联的计数器(引用计数),当一个shared_ptr的计数器为0时,它就会自动释放自己所管理的对象。

8、shared_ptr的析构函数会递减它所指向对象的引用计数。如果引用计数变为0,shared_ptr的析构函数就会销毁对象并释放内存。

9、使用动态内存的三种原因:程序不知道需要使用多少对象、程序不知道对象的准确类型、程序需要在多个对象之间共享数据。

StrBlob的ADT接口:

class StrBlob
{
 public:
    typedef std::vector<std::string>::size_type size_type;
    StrBlob();
    StrBlob(std::initializer_list<st::string>il);
    size_type size() const {return data->size();}
    bool empty() const {return data->empty:();}
    void push_back(const std::string &t) {data->push_back(t);}
    void pop_back();
    std::string& front();
    std::stirng& back();
 private:
   std::shared_ptr<std::vector<satd::string>> data;
   void check(size_type i , const std:: strign &msg) cosnt;//const成员函数 
}

StrBlob的接口实现:

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();
}
void StrBlob::pop_back()
{
   check(0,"pop_back on empty StrBlob");
   data->pop_back:();
}

10、使用new和delete分配,释放动态内存。

11、自由空间分配的内存是无名的,因此new无法为其分配的对象命名,而是返回一个指向该对象的指针。

12、默认情况下,动态分配的对象是默认初始化的。也可以使用直接初始化的方式来初始化一个动态分配的对象。

int * pi = new int(1024);//指向一个初始化了的内存
string *pi= new int;//指向一个未初始化的内存

13、一个动态分配的const对象必须进行初始化。

14、通过delete表达式将动态分配的内存归还给系统,delete表达式接受一个指针,指向我们要释放的对象。

15、由内置指针管理的动态内存在被显示的释放前一直都会存在。

16、野指针:指针操作超越了变量的作用范围;空悬指针:指针指向内存的对象已经被销毁,但是内存还没释放。

16、shared_ptr和new结合使用:

shared_ptr<int> p1= new int (1024);//错误,必须使用直接初始化形式
shared_ptr<int> p2(new int (1024));//直接初始化,正确

17、当一个shared_ptr绑定到一个普通指针时,我们就将内存的管理责任交给了sahred_ptr。(不能使用普通指针访问该内存)

18、get用来将指针的访问权限传递给代码,该代码不能delete该指针指向的内存。

19、当程序执行发生错误时,智能指针指向的内存仍能被正确释放。但是,动态分配的内存就不能被正确释放。

20、智能指针陷阱:

  • 不能使用相同的内置指针初始化多个智能指针
  • 不能delete get()返回的指针。
  • 不使用get初始化或reset另外一个智能指针。
  •  使用get()返回的指针时,当最后一个智能指针被销毁时,指针就已经无效了。
  • 如果使用智能指针管理的资源不是new分配的对象,需要提供一个删除器。

21、unique_ptr定义时,需要绑定到一个new返回的指针上。且需要直接初始化。

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

22、不能拷贝或赋值unique_ptr,但可以通过调用release或reset将指针的所有权从一个(非const)unique_ptr转移到另外一个unique_ptr。

unique_ptr <string> p3(new stirng("Trex"));
p2.reset(p3.release());//release释放了原来p2指向的内存空间 

23、不能拷贝unique_ptr的规则有一个例外:可以拷贝一个将要被销毁的unique_ptr。

24、unique_ptr默认情况下把delete作为它指向的对象。可以重载unique_ptr中默认的删除器。

25、weak_ptr是一种不控制所指向对象生成期的智能指针,它指向一个由shared_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变它的应用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。

auto p = mak_shared<int>(42);
weak_ptr<int> wp(p);//p的引用计数不改变
class StrBlobPtr
{
   public:
       StrBlobPtr():curr(0){}
       StrBlobPtr(StrBlob&a,size_t sz=0):wptr(a.data),curr(sz){}
       std::string & deref() const;
       StrBlobPtr& incr();
   private:
       std::shared_ptr<std::vector<std::string>> check(std::size)t,const std::string&) const;
       std::weak_ptr<std::vector<std::string>> wptr;
       std::size_t curr;
}
std::shared_ptr<std::vector<std::string>>
StrBlobPtr::check(std::size_t i,const std::string &masg) const 
{
   auto ret = wkptr.lock;()//vector存在吗?
   if(!ret)
     throw std::runtime_error ("unbound StrBlobPtr");
   if(i>=ret->size())
     throw std::out_of_range(msg);
   return ret ;//
}

26、大多数容器使用标准库容器而不是动态分配的数组。

int *pia = new int[get_size()];
方括号中的大小必须是整型,不必是常量。

27、由于分配的内存并不是数组类型,因此不能对动态数组调用begin或end。也不能用范围for语句来处理动态数组中的元素。

28、默认情况下,new分配的对象都是默认初始化的。

29、不能创建一个大小为0的静态数组对象,但是当n=0时,调用new[n]是合法的。

char arr[0];//错误,不能定义长度为0的数组
char *cp = new char[0];//正确,但cp不能解引用

30、释放动态数组必须用delete[];

31、可以使用unique_ptr来管理动态数组,当unique_ptr指向一个数组时,可以使用下包来范问数组中的元素。

unique_ptr<int []> up (new int[10]);

32、与unique不同,sharedf_ptr不支持管理动态数组。

33、使用shared_ptr管理new分配的内存,使用unique_ptr管理new[]分配的内存。

34、allocator是一个模板,为了定义一个allocator对象。我们必须指明这个allocator可以分配的对象类型。

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

35、allocator分配的内存是未构造的,我们需要在此内存中构造对象。

auto q = p;
alloc.construct(q++);//*q为空字符串
alloc.construct(q++,10,'c');//*q为ccccc
alloc.construct(q++,"hi");//*q为hi

36、用完对象后,必须对每个构造的元素调用destroy来销毁。

while(q!=p)
    alloc.destry(--q);

37、一旦元素被毁灭后,就可以重新使用这部分内存保存其它string,也可以释放。

alloc.deallocate(p,n);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值