C和CPP内存分配

C语言内存分配及释放

#include <stdio.h>
#include <stdlib.h>
int main(){
    int n;
    scanf("%d",&n);
    int *p=(int *) malloc(n*sizeof (int));
    for (int i = 0; i < n; ++i) {
        p[i]=i;
    }

    for (int i = 0; i < n; ++i) {
        printf("%d\n",p[i]);
    }
    free(p);
    p=NULL;
}

20220115181505
20220115181523
20220115181750
20220115181815
如果不释放,heap中太满了,则*ptr中存放null
20220115181950
20220115182140
用free(指针名)释放内存
20220115184822
20220115185137

内存泄漏

20220115191534
20220115191608
20220115191703

C++内存分配及释放

20220115191342

C++智能指针

教程1: SMART POINTERS in C++

  • unique ptr
    20220115205255
    20220115205402
    20220115205544
    20220115205652
  • shared ptr
    20220115210022

在离开原来的scope后,原来shared的指针计数就自动减少了
20220115210345

教程2

20220115193109

20220115193804

20220115201305

#include "demo1.h"
#include <iostream>
#include <memory>
using namespace  std;
class Foo{
    int x;
public:
    explicit Foo(int x):x(x){};
    int getX(){
        return x;
    }
    ~Foo(){
        cout<<"Foo Dest"<<endl;
    }
};
int main(){
//    如果不加 delete f;,则存在内存泄漏,即不会调用析构函数
    Foo *f=new Foo(10);
    cout<<f->getX()<<endl; //
    delete f;
    cout<<"======"<<endl;

//    采用了智能指针,不存在内存泄漏
    unique_ptr<Foo> p1(new Foo(10)); // 方式1
    unique_ptr<Foo> p2=make_unique<Foo>(20); // 方式2
    Foo *f1=new Foo(30); //方式3
    unique_ptr<Foo> p3(f1);

    cout<<p1->getX()<<endl; // 使用1
    cout<<(*p2).getX()<<endl; //使用2
    cout<<p3->getX()<<endl;
    cout<<"======"<<endl;
    Foo *f2=p2.get();
    Foo *f3=p2.release();
    cout<<f2->getX()<<endl; //
    cout<<(*f3).getX()<<endl; //
    cout<<"======"<<endl;
    p2.reset(f3);
    cout<<f2->getX()<<endl; //
    return 0;
}
//10
//Foo Dest
//======
//10
//20
//30
//======
//20
//20
//======
//20
//Foo Dest
//Foo Dest
//Foo Dest

20220115203238

#include "demo1.h"
#include <iostream>
#include <memory>
using namespace  std;
class Foo{
    int x;
public:
    explicit Foo(int x):x(x){};
    int getX(){
        return x;
    }
    ~Foo(){
        cout<<"Foo Dest"<<endl;
    }
};
int main() {
    shared_ptr<Foo>sp(new Foo(100));
    cout<<sp->getX()<<endl;
    cout<<sp.use_count()<<endl;
    cout<<"======"<<endl;
    shared_ptr<Foo>sp1=sp; // 如果用赋值,则计数增加
    cout<<sp.use_count()<<endl;
    cout<<sp1.use_count()<<endl;
    cout<<"======"<<endl;
    shared_ptr<Foo>&sp2=sp; // 如果传引用,则计数不会有影响
    cout<<sp2.use_count()<<endl;
    cout<<"======"<<endl; // 如果传指针,则计数不会有影响
    shared_ptr<Foo>*sp3=&sp; // 如果传引用,则计数不会有影响
    cout<<sp3->use_count()<<endl;
}
//100
//1
//======
//2
//2
//======
//2
//======
//2
//Foo Dest

多线程中使用
20220115204704
20220115204932

在数组中使用

unique_ptr 的数组智能指针,没有 和 -> 操作,但支持下标操作[]>
shared_ptr 的数组智能指针,有
和 -> 操作,但不支持下标操作[],只能通过 get() 去访问数组的元素>
shared_ptr 的数组智能指针,必须要自定义deleter

  • unique_ptr

数组与智能指针

  • shared_ptr
#include <iostream>
#include <cstdlib>
#include <vector>
#define N 2
using namespace std;
int main() {
    // allocate N int memory blocks
    int* ptr = (int*) malloc(N * sizeof(int));
    for (int i = 0; i < N; i++) {
        ptr[i] = i;
    }
//   分配一片新的内存空间,并对其赋值
    int* ptr1 = (int*) malloc(N * sizeof(int));
    ptr1=ptr; //这里是浅拷贝
    // print the values in allocated memories
    for (int i = 0; i < N; i++) {
        // ptr[i] and *(ptr+i) can be used interchangeably
        cout << ptr1[i]<< endl;
        cout <<*(ptr1+i)<< endl;
    }
//    使用 shared_ptr 指针,然后用*(ptr2.get()+i) 取里面的元素
    std::shared_ptr<int> ptr2(new int[N](), std::default_delete<int[]>());
    ptr2= static_cast<const shared_ptr<int>>(ptr);
    for (int i = 0; i < N; i++) {//
        cout << ptr2.get()[i] << endl; // 或者 cout << *(ptr2.get()+i) << endl;
    }
    return 0;
}

另外,使用shared_ptr过程中有几点需要注意:构造shared_ptr的方法,如下示例代码所示,我们尽量使用shared_ptr构造函数或者make_shared的方式创建shared_ptr,禁止使用裸指针赋值的方式,这样会使shared_ptr难于管理指针的生命周期。

// 使用裸指针赋值构造,不推荐,裸指针被释放后,shared_ptr就野了,不能完全控制裸指针的生命周期,失去了智能指针价值
int *p = new int(10);
shared_ptr<int>sp = p;
delete p; // sp将成为野指针,使用sp将crash
// 将裸指针作为匿名指针传入构造函数,一般做法,让shared_ptr接管裸指针的生命周期,更安全
shared_ptr<int>sp1(new int(10));
// 使用make_shared,推荐做法,更符合工厂模式,可以连代码中的所有new,更高效;方法的参数是用来初始化模板类
shared_ptr<int>sp2 = make_shared<int>(10);

   转载规则


《C和CPP内存分配》 M 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录