C++(2)----智能指针与动态内存

C++ 11提供的智能指针有:shared_ptr、unique_ptr、weak_ptr。在 头文件 memory 中。

一、new delete 直接管理内存

1、初始化

string * ps = new string // 初始换为一个空string
int * pi = new int ;//pi 指向一个未初始化的int,*pi 未定义

int * pi = new int(1024); // pi 指向的对象值为1024
string *ps = new string(10,‘9‘) ; // *ps 为"9999999999"

vector<int> *pv = new vector<int>{0,1,2,3,4,5,6,7,8,9};

2、释放delete

int i, *pi1 = &i,  *pi2 = nullptr;
double *pd = new double(33),  *pd2 =pd;

delete i;  // 错误,, i不是一个动态分配的指针
delete pi1;  // 未定义错误,  pi1指向一个栈内存指针
delete pd;   //正确
delete pd2;  //未定义错误, pd2指向的内存已经被释放
delete pi2;   //正确:不能释放一个空指针

delete 之后应该重置指针, 

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

3、使用new delete 管理内存常出现的问题

    没有delete内存,造成内存泄漏

    使用已经释放掉的对象

    同一块内存释放两次

二、shared_ptr:

  允许多个指针指向同一个对象。

定义与初始代码如下:

// 定义shared_ptr ,默认初始化为空指针
shared_ptr<string> p1;
shared_ptr<list<int>> p2;

// make_shared 函数, 头文件 memory
// 返回一个shared_ptr,
// make_shared<T>(args)  使用args初始化对象
shared_ptr<int> p3 = make_shared<int>(42);
shared_ptr<string> p4 = make_shared<string>(10,‘9‘) // "9999999999"

shared_ptr<int> p5 = make_shared<int>(); //初始化为 0

和new 结合初始换

shared_ptr<int>p2(new int(42));

// 不能混淆普通指针和只能指针
shared_ptr<int> p1 = new int(1000);  // 错误
shared_ptr<int> p2(new int(1024));  // 正确

// 错误
shared_ptr<int> clone(int p) {
        return new int(p);
}
// 正确
shared_ptr<int> clone(int p) {
        return shared_ptr<int>(new int(p));
}

shared_ptr的拷贝和赋值、自动释放

引用计数; 当对象不再使用时,shared_ptr 会自动释放动态对象;

auto p = make_shared<int>(42); //p指向的对象只有p一个引用者
auto q(p);  // 递增一个引用计数

auto r = make_shared<int>(42);   //引用计数为1
r=q ;    //  给r赋值;  r原来指向的对象引用计数减1; q指向的对象引用计数+1; r原来指向的对象没有引用,自动释放

当引用计数为0是,内存会被释放,当普通指针  和智能指针混用是可能会出现错误。

// 一个函数,参数为 shared_ptr<int>
void process(shared_ptr<int> ptr) {A
      // 使用ptr
}// ptr离开作用于,销毁释放

/********   正确 ********/
shared_ptr<int> p(new int(42));   // 引用计数为1
process(p); // 参数作为值传递,在函数内部引用计数为2,之后为1
int i = *p; //内有问题, 引用计数值为1;

/*********  错误 ********/
int *x(new int(1024));   // 这是一个普通的指针
process(x) ; // 错误,普通指针不能转换为 shared_ptr<int>
porcess(shared_ptr<int>(x)); //合法,但是危险,函数结束后,会释放内存
int j =*x ; // 错误,此时内存已经被释放 

谨慎的使用get() 函数,只有保证内存不被释放的前提现使用。

不能用get 初始化另一个智能指针,或为另一个智能指针赋值

// 谨慎使用 get() 函数

shared_ptr<int> p(new int(42));  // 引用计数为1
int * q = p.get(); // 合法,但是保证内存释放的时机

{// 程序块
  // 不要使用get() 对另一个智能指针初始化,这样对同一块内存,有多个计数
  shared_ptr<int>(q);
}// q被销毁释放
int foo = *p; // 此时p所指向的内存已经被释放

在发生异常时,智能指针也能保证内存被释放

// 使用 new 分配内存,应当注意由于分支  和 异常造成的内存泄漏
void f()
{
      int *ip = new int(42);  // new 动态分配
      // 发生异常
      delete ip;    // 之前发生异常,这里可能造成内存泄漏
} 

// 使用智能指针, 在发生异常时,内存也会被释放
void f()
{
     shared_ptr<int> sp (new int(42)); // 分配一个新对象
     // 发生异常

}//  在函数结束时,shared_ptr 被销毁,同时释放指向的内存

资源管理《c++primer》:

三、unique_ptr:

独占,同一时间只有一个智能指针可以指向这个对象。

不支持普通的拷贝,和赋值

unique_ptr<string> p3 (new string ("auto"));    //#4
unique_ptr<string> p4;                         //#5
p4 = p3;                                     //   出错unique_ptr<string> p4(p3);                  //出错:不支持拷贝

unique_ptr<string> p2(p1.release())       // release 将p1置为空unique_ptr<string> p3(new string("Trex"));// 将所有权从p3转移给p2p2.reset(p3.release());                

四、weak_ptr

不控制所指向对象生存期。

指向由一个shared_ptr管理的对象(由shared_ptr管理生命周期)

将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数

// 初始化
auto p = make_shared<int>(42);
weak_ptr<int> wp(p);   // 若共享,p的技术不变

// 生命周期由shared_ptr 管理,因此weak_ptr指向的对象可能为空
// 可使用lock 检查是否为空
// lock 返回一个指向共享对象的shared_ptr
if(shared_ptr<int> np = wp.lock())
{
.......
}

五、智能指针与动态数组

int *pia = new int[10];   // 10个未初始化的int
int *pia2 = new int[10]();  //10个值初始化为0的int
string *psa = new string[10]; //10个空string
string *psa2 = new string[10](); // 10个空string

int * pia3 = new int[3]{0,1,2};

delete [] pia;

unique_ptr<int[]> up(new int[10]);up.release(); //自动使用delete[] 销毁指针
// allocator  在头文件memory 中
//  将内存分配和对象构造分离
//  分配原始 未构造
// 是一个模板

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

参考:

https://blog.csdn.net/k346k346/article/details/81478223

https://www.cnblogs.com/WindSun/p/11444429.html

《c++ primer》第12章

https://www.cnblogs.com/KunLunSu/p/7861330.html

原文地址:https://www.cnblogs.com/feihu-h/p/12205531.html

时间: 2024-11-10 14:27:58

C++(2)----智能指针与动态内存的相关文章

第12章 动态内存

全局对象:启动时分配,结束时销毁 局部对象:程序块内分配,程序块外销毁 static对象:第一次使用分配,结束时销毁 动态内存使用new来分配对象,使用delete销毁对象 12.1两种智能指针 #include<memory> shared_ptr: 多个指针可以指向同一个对象 unique_ptr: 独占指向的对象 weak_ptr: 一个伴随类,指向shared_ptr管理的对象,是弱引用 智能指针也是模板,定义时需要指明类型 shared_ptr<string> p1; s

《C++primer》v5 第12章 动态内存 读书笔记 习题答案

这一章暂时没写完,先留着以后再写. 在C++程序中,程序员可以给手动开辟内存,但是这块内存需要手动释放,不便管理,因此新标准提供智能指针类型来管理动态对象.它负责自动释放所指向的对象. shared_prt允许多个指针指向同一个对象 unique_ptr独占所指向的对象 weak_ptr是一个弱引用,指向shared_ptr所管理的对象 一些操作: p=q;//递减p的引用计数,递增q的引用计数 shared_ptr<T> p(q);//p是q的拷贝,递增q的引用计数 通过make_share

智能指针的简单实现

智能指针:动态的管理开辟的内存,防止人为的内存泄漏. SharedPtr的实现: 原理:使用引用计数的原理使多个对象可以指向一块空间. #define  _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; template <class T> class SharedPtr { public: SharedPtr() :_count(new int(1)), _ptr(NULL) {} SharedPtr(

Qt 智能指针学习(7种QT智能指针和4种std智能指针)

从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel *label = new QLabel("Hello Dbzhang800!"); label->show(); return app.exec(); } 在  从 Qt

Qt 智能指针学习(7种QT的特有指针)

从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel *label = new QLabel("Hello Dbzhang800!"); label->show(); return app.exec(); } 在  从 Qt

Chapter12:动态内存

智能指针——shared_ptr 为了更容易地使用动态内存,新的标准提供了智能指针来管理动态对象.智能指针的行为类似常规指针,重要的区别是它负责自动释放指向的对象. 智能指针的使用方式与普通指针类似.解引用一个智能指针返回它指向的对象. 1 if (p1 && p1->empty()) 最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准库函数 make_shared<T>(args); //返回一个shared_ptr, 指向一个动态分配的类型为T

C++ Primer学习总结 第12章 动态内存

第12章 动态内存 1.    申请并使用shared_ptr.  P400 2.    shared_ptr计数. P402 赋值, 拷贝, 向函数传递一个智能指针, 或函数返回一个智能指针都会增加当前智能指针的计数. 3.    不同对象间利用智能指针共享数据的例子. 4.    使用new来动态申请内存. P407 默认情况下,new申请的内存对象都是默认初始化的. 5.    new申请的const对象必须初始化. P408 如果申请内置类型, 那么必须用括号()初始化. 如果申请类类型

Qt 智能指针学习

从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel *label = new QLabel("Hello Dbzhang800!"); label->show(); return app.exec(); } 在  从 Qt

C++ 智能指针(shared_ptr/weak_ptr)源码分析

C++11目前已经引入了unique_ptr, shared_ptr, weak_ptr等智能指针以及相关的模板类enable_shared_from_this等.shared_ptr实现了C++中的RAII机制,它不仅仅具有一般指针(build-in/raw)的特性,更重要的是它可以自动管理用户在堆上创建的对象的生命周期,让用户不用负责内存回收,避免内存泄漏.一般的智能指针都定义为一个模板类,它的类型由被管理的对象类型初始化,内部包含了指向该对象的指针以及指向辅助生命周期管理的管理对象的指针.