C++智能指针学习和侯捷C++笔记2

Apr 29,2018   2329 words   9 min

Tags: C/C++

1.堆(Heap)与栈(Stack)

由普通方式新建出来的对象属于stack object,利用new方式创建出来的对象属于heap object。它们的区别在于不同的生命周期。 简单来说就是栈对象的声明周期是当前所在的作用域(Scope),超出这个作用域就会被回收。 堆对象生命周期是整个函数,直到结束。 注意在代码中使用new创建出来的对象,在程序结束时都应该手动delete,否则就有可能造成内存泄漏出错。 而且形式要对应,如new char[],那么对应是delete []new数组,删数组,new对象,删对象。否则形式不对应也会造成内存泄露。

2.newdelete的解析

new的操作是先分配内存,再调用构造函数。 整个new的操作可以理解为三个操作,分别是:分配内存、指针转型、调用构造函数。 这里对指针转型的命令static_cast在前面也提到过,用于对指针类型进行转换。

delete的操作是先调用析构函数,再释放内存。 字符串本身只是一个指针而已。

3.动态分配内存块

每一小格代表4个字节。在调试模式下,编译器会自动在前面增加32个字节,后面增加4个字节(灰色部分)。 并且在首位还各有一个4字节的cookie(棕色部分)。当这些添加完成后,看其是否是16的倍数,如果不是就补充成16的整数倍(绿色部分)。 而Release模式下就没有灰色部分。只有它本身+cookie+填充部分(如果需要的话)。 从这角度也可以看出来,Debug模式要比Release更加消耗内存。 对于数组而言,也与对象类似。 不同的是在VC中,会在数组的头部用一个整数(4字节)来记录数组长度。 如果array new没有搭配array delete,那么发生内存泄漏的,不是本身数组的这一部分内存。 而是数组中每个元素的指针所指向的那块内存。 例如一个string数组,如果用delete,那么会造成后续字符串指向的那块内存空间泄漏,没有指针再指向它们了,不受控制了。 当然如果说数组元素中没有指针,用delete也不会造成内存泄漏。 但是从养成一个好习惯的角度考虑,写代码要尽量严谨。 因此只要是对于数组,即使数组元素没有指针,也建议用array delete。

4.C++智能指针学习

智能指针共分为4种,即auto_ptrunique_ptrshared_ptrweak_ptr。 智能指针的作用是管理一个指针,因为存在以下这种情况:申请的空间在函数结束时忘记释放,造成内存泄漏。 所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间。 智能指针都在头文件memory.h中。

这里重点学习一下shared_ptrshared_ptr是智能指针(smart pointer)的一种,作用如同指针,但会记录有多少个shared_ptrs共同指向一个对象。 这便是所谓的引用计数(reference counting)。一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。 这在非环形数据结构中防止资源泄露很有帮助。使得指针可以共享对象,并且不用考虑内存泄漏问题。

shared_ptr可以支持普通指针的所有操作,完全可以像操作普通指针一样操作智能指针。 可以通过三种方式得到:

  • 1.通过一个指向堆上申请的空间的指针初始化(切记不要用栈上的指针,否则,当智能指针全部释放控制权(栈中的对象离开作用域本身就会析构一次),将会析构对象,导致出错)
  • 2.通过make_shared函数得到
  • 3.通过另外一个智能指针初始化

下面这段代码简单演示了shared_ptr的使用。

#include <memory>  
#include <iostream>  
int main()  
{  
    int *p = new int(30);  
    std::shared_ptr<int> bptr(p);//方式1  
    std::shared_ptr<int> aptr = std::make_shared<int>(20);//方式2
    std::shared_ptr<int> cptr(aptr);//方式3
    std::cout << "aptr.use_count() = " << aptr.use_count() <<"  value = "<<*aptr<<std::endl;//use_count 是引用计数器  
    std::cout << "bptr.use_count() = " << bptr.use_count() <<"  value = "<<*bptr<<std::endl;  
    std::cout << "cptr.use_count() = " << cptr.use_count() <<"  value = "<<*cptr<<std::endl;   
}  

运行结果如下:

5.参考资料

  • https://blog.csdn.net/zy19940906/article/details/50470087
  • https://blog.csdn.net/zy19940906/article/details/50481969
  • https://blog.csdn.net/man_sion/article/details/77196766
  • https://www.cnblogs.com/lanxuezaipiao/p/4132096.html

本文作者原创,未经许可不得转载,谢谢配合

返回顶部