【C++ Primer 第十二章】 shared_ptr和new的结合使用

shared_ptr和new的结合使用

• 如果我们不初始化一个智能指针,它就会被初始化一个空指针。

• 一个shared_ptr默认初始化为一个空指针。我们也可以使用new返回的指针来初始化一个shared_ptr:

shared_ptr<double> p1;                // shared_ptr可以指向一个double
shared_ptr<int> p2(new int(42));      // p2指向一个值为42的int  

• 接受指针参数的智能指针构造函数是explicit的。因此,我们不能将一个内置指针隐式的转换为一个智能指针,必须使用直接初始化形式:

shared_ptr<int> p1(new int(42));      // p1指向一个值为42的int
shared_ptr<int> p2 = new int(1024);   // 错误,不能将一个内置指针隐式转化为智能指针。
 1 shared_ptr<int> clone(int p)
 2 {
 3     return new int(p);        // 错误,不能隐式转化
 4
 5 }
 6
 7 shared_ptr<int> clone(int p)
 8 {
 9     return shared_ptr<int>(new int(p));   // 正确
10 }

定义和改变shared_ptr的其他方法

• 默认情况下,一个用来初始化智能指针的普通指针必须指向动态内存,因为智能指针默认使用delete释放它所关联德邦对象。

不要混合使用普通指针和智能指针

考虑下面对shared_ptr进行操作的函数:

void process(shared_ptr<int> ptr)
{
   // 使用ptr
}  // ptr离开作用域,被销毁  

使用次函数的正确方法是传递给它一个shared_ptr:

shared_ptr<int> p(new int(42));   // 引用计数为1
process(p);                       // 拷贝p,在函数结束前引用计数为2,函数执行结束后,引用计数变为1
int i = *p;                       // i == 42

由于不能将一个内置指针隐式转换为一个shared_ptr,因此,我们不能将一个内置指针直接传递给process函数,但可以传递给它一个临时的shared_ptr,这个shared_ptr使用一个内置指针显示构造的:

int* x(new int(1024));
process(x);                      // 错误,不能将一个int*转换为一个shared_ptr,因位构造函数时explicit的
process(shared_ptr<int>(x));    // 合法的,但x所管理的内存会被释放  

int j = *x;     // 错误,x是一个空悬指针!  

也不要使用get初始化另一个智能指针或为智能指针

• 智能指针类定义了一个get的成员函数,该成员函数返回一个内置指针,指向智能指针管理的对象。此函数为了向不使用智能指针的代码传递一个普通指针,使用get返回的指针的代码不能delete此指针。

将一个智能指针绑定到get返回的指针上时错误的:

 1 shared_ptr<int> p(new int(1024));
 2 int* q = p.get();
 3
 4 { // 新的作用域
 5
 6     shared_ptr<int> p1(p);
 7
 8 } // 作用域结束,p1被销毁,p1所管理的对象被释放
 9
10 int foo = *p; // 未定义,p指向的内存已经被释放了  

其他shared_ptr操作

• reset操作:

p = new int(1024);       // p是一个shared_ptr类型, 发生错误,不能将一个指针赋予shared_ptr
p.reset(new int(1024));  // p指向一个新对象  

• unique操作: 如果一个shared_ptr对象唯一指向它所管理的内存对象,则返回true。

if (!p.unique())     // 如果p补是它所管理对象的唯一引用者,则为它重新分配
   p.reset(new int(100));
*p += newVal;        // 现在p是唯一的用户,可以改变对象的值  

智能指针和异常

• 如果程使用智能指针, 即使程序过早结束,智能指针也能确保内存不再需要时将其释放。

void f()
{
    shared_ptr<int> sp(new int(42));
    // 抛出异常,未在f中捕获
    // 函数结束后shared_ptr正确释放资源
} 

• 如果在new和delete之间发生异常,且异常未在f中捕获,则内存永远不能释放。在函数之外没有指针指向这块内存,异常就无法释放它。

void f()
{
    int* ip = new int(42);
    // 发生异常,且在f中未捕获
    delete ip;
}   

原文地址:https://www.cnblogs.com/sunbines/p/8946600.html

时间: 2024-10-08 19:31:54

【C++ Primer 第十二章】 shared_ptr和new的结合使用的相关文章

C++Primer 第十二章

//1.标准库提供了两种智能指针类型来管理动态对象,均定义在头文件memory中,声明在std命名空间. // shared_ptr:允许多个指针指向同一个对象. // unique_ptr:独占所指的对象. // 标准库还定义了weak_ptr的伴随类,它是一种弱作用.指向shared_ptr所管理的对象. //2.shared_ptr和unique_ptr均支持的操作: shared_ptr<T> sp unique_ptr<T> up:空智能指针,指向类型为T的对象 p :将

C++ primer 第十二章笔记之 动态内存

动态内存: 运算符:new,delete 智能指针: 头文件:memory shared_ptr:允许多个指针指向同一个对象; unique_ptr:"独占"所指向的对象; weak_ptr:一种弱引用,指向shared_ptr所管理的对象; shared_ptr类 智能指针也是模板,创建指针时,提供指针指向的类型; //创建: shared_ptr<string> p1; //若p1不为空,检测它是否指向一个空string if( p1 &&p1->

C++ primer 第十二章笔记之 动态数组

new与数组 为了让new分配一个对象数组,必须在类型名之后跟[].在其中指明分配的数目; int *pia = new int [ get_size() ]; //[]内必须为整型,但不必是常量; typedef int arrT[24]; int * p = new arrT; //分配一个24个int的数组,p指向第一个int; 初始化,C++11:可用花括号{}; 动态分配一个空数组是合法的; 释放动态数组: delete p; delete [] pa; 智能指针与动态数组: 标准库提

C++primer第十二章读书笔记---动态内存与智能指针

    目前为止我们使用过的静态内存,栈内存和内存池,静态内存用来保存局部static对象.类static成员,以及定义在任何函数之外的成员.栈内存用来保存定义在函数内部的非static成员,分配在静态 内存或栈内存中的对象由编译器自动创建或销毁,对于栈对象仅在其定义的程序块运行时才有效,static对象在程序运行之前分配,程序结束时销毁.除了静态内存和栈内存外,每个程序还拥有一个内存池(堆)在堆上分配动态对象,当动态对象不再使用时,我们必须显示的销毁它.     (一).动态内存与智能指针  

【C++ Primer 第十二章】 unique_ptr

unique_ptr • 一个unique_ptr拥有它所管理的对象,与shared_ptr不同,unique_ptr指向的对象只能有一个用户.当unique_ptr被销毁后,它所指向的对象也被销毁. • 与shared_ptr不同,没有类似make_shared_ptr的标准函数返回一个unqiue_ptr,定义一个unique_ptr时,需要将其绑定到一个new返回的指针上,类似shared_ptr,初始化unique_ptr必须采用直接初始化形式: unique_ptr<double>

C++ Primer之 十二章 类

1.关于类的const对象 const对象只能调用声明为const的成员函数,在这篇csdn博客中也讨论了这个问题. 究其原因是因为 const 对象A 调用了非const函数F, F因为没有const约束可以修改A对象内的成员, 这不就违反了原来对A 声明const的本意了吗? 反之,非const对象调用const函数则是可以的. 2.基于const的重载 关于const修饰的成员函数可以详见这篇新浪博客! 基于成员函数是否为const,可以重载一个成员函数: 基于一个指针形参是否为const

c++ primer plus(第6版)中文版 第十二章编程练习答案

第十二章编程练习答案 12.1根据以下类声明,完成类,并编小程序使用它 //12.1根据以下类声明,完成类,并编小程序使用它 #include <iostream> #include <cstring> using namespace std; class Cow{ char name[20]; char * hobby; double weight; public: Cow(); Cow(const char * nm, const char * ho, double wt);

C Primer Plus 第十二章程序清单……2015.5.10

C Primer Plus           第五版 第十二章  程序清单 #include<stdio.h> int main() { int x=30; printf("x in outer block:%d\n",x); { int x=77; printf("x in inner block:%d\n",x); } printf("x in outer block:%d\n",x); while(x++<33) { i

C primer plus 第五版十二章习题

看完C prime plus(第五版)第十二章,随带完成了后面的习题. 1.不使用全局变量,重写程序清单12.4的程序. 先贴出12.4的程序,方便对照: 1 /* global.c --- 使用外部变量 */ 2 #include <stdio.h> 3 int units = 0; //一个外部变量 4 void critic(void); 5 int main(void) 6 { 7 extern int units; 8 9 printf ("How many pounds