《白话C++》第10章 STL和boost,Page67 std::auto_ptr

std::auto_ptr可以不经意间转移裸指针控制权

std::auto_ptr持有裸指针的控制权,却可以随随便便看似不经意地转移给另一个auto_ptr:

#include <iostream>
#include <memory>using namespace std;struct S
{int a;void SetA(int a){this->a = a;}~S(){cout << "~S: bye-bye" << endl;}
};void test_auto_ptr_crash()
{auto_ptr <S> aps(new S);auto_ptr <S> aps2(aps); //转移对裸指针的所有权aps2->SetA(99);aps->SetA(100); //有可能造成程序挂掉
}

023行,aps获得并负责管理一个新的裸指针(通过new S所得);

024行,看是普通的“拷贝构造”操作,实际确实在做转移操作,aps拱手让出的原是它拥有且负责管理的裸指针

025行,aps2拥有,并可以控制该裸指针了

026行,“旧人”aps还想操作裸指针,但此时它拥有的裸指针是“nullptr”。

auto_ptr作为入参,传给函数:

再看看复杂点的情况,比如将auto_ptr作为入参,传给函数:

void foo(auto_ptr<S> aps)
{;
}void call_foo()
{auto_ptr <S> aps(p);/**< 当实参传递时,需要复制,这一复制,原auto_ptr即失去了原有的裸指针 */foo(aps);cout << "===============" << endl;aps->SetA(100);//程序通常要挂掉……
}

演示auto_ptr作为入参:

foo函数的入参是一个auto_ptr,而不是“auto_ptr <S>&”或“auto_ptr<S>*”,因此当实参传递时,需要复制,这一复制,原auto_ptr即失去了原有的裸指针,那就试试将入参改成auto_ptr的引用:

入参改为auto_ptr的引用:

void foo2(auto_ptr<S> & aps)
{;
}

这将传递,没有发生裸指针转移所有权的事,但进入函数之后,万一又有复制的需要:

void foo2(auto_ptr<S> & aps)
{//如果有复制,还是会被转移走的。auto_ptr<S> aps2(aps);
}

以引用方式传递auto_ptr给某个函数,调用者更加没有安全感了,因为调用处原auto_ptr到底会不会被“转移”走,调用者完全不可控。

常量引用:

如果一个函数明确不准备转移auto_ptr入参的所有权,解决方法是“常量引用”:

/**< 明确不准备转移auto_ptr入参的所有权,解决方法是“常量引用” */
void foo3(auto_ptr <S> const& aps)
{auto_ptr <S> aps2(aps); //编译不过去aps.release(); //也编译不过去//delete aps.get();//代码阻止不了某些程序员的猥琐
}

foo3函数作者感到迷惑了:我只是想以“aps”为模子复制一份,为什么编译不能过呢?

auto_ptr本身也感到委屈:“我早就说过了,我的‘复制’就是转移,是你们记不住呀”

auto_ptr类模板的拷贝构造函数:

典型的拷贝构造auto_ptr的拷贝构造

class XXX

{

public:

        ...

        XXX(XXX const& other);

        ...

};

template <typename T>

class auto_ptr

{

public:

        ...

        auto_ptr(auto_ptr& other)

        ...

};

对比两边的构造函数声明,左边入参带有const修饰,右边的没有。auto_ptr没有欺骗我们,它特意声明拷贝构造时的入参不能是常量,原因就在于它复制other时,还会修改other的内容,这是合法的,因为C++没规定拷贝构造的入参一定是const。只是这违反了直觉,违反了“拷贝构造”的语义。所以C++标准委员会决定抛弃auto_ptr。

auto_ptr作为函数返回值:

auto_ptr作为函数返回值的做法,在旧代码中很常见。

std::auto_ptr <S> CreateS()
{...S* ps = new S;...return std::auto_ptr <S> (ps);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/472967.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

爱上JVM——常见问题(一):JVM组成

1 JVM组成 1.1 JVM由那些部分组成&#xff0c;运行流程是什么&#xff1f; 难易程度&#xff1a;☆☆☆ 出现频率&#xff1a;☆☆☆☆ JVM是什么 Java Virtual Machine Java程序的运行环境&#xff08;java二进制字节码的运行环境&#xff09; 好处&#xff1a; 一次编写&…

如何修复Microsoft Edge不能以全屏模式打开​?这里提供几个故障排除方法

随着越来越多的Windows 10用户将Edge设置为默认浏览器&#xff0c;各种错误和小故障层出不穷。例如&#xff0c;许多用户抱怨他们无法在全屏模式下启动Edge。如果你正在寻找解决方案来解决这个恼人的问题&#xff0c;请按照下面的故障排除步骤进行操作。 修复Microsoft Edge不…

最大N个数与最小N个数的和 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 给定一个数组&#xff0c;编写一个函数来计算它的最大N个数与最小N个数的和。你需要对数组进行去重。 说明&#xff1a; 数组中数字范围[0, 1000] 最大N个数与…

ClickHouse--09--SQL DML 操作

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 SQL DML 操作1.Insert 插入2.update 更新3.delete 删除 SQL DML 操作 DML:Data Manipulation Language,数据操纵语言。 List itemClickHouse 中 DML 语言包含插入…

【JavaEE】_线程与多线程的创建

目录 1. 线程的概念 2. 创建与使用多线程 2.1 方式1&#xff1a;继承Thread类 2.2 方式2&#xff1a; 实现Runnable接口 2.3 以上两种创建线程方式的对比 3. 多线程的优势-增加运行速度 1. 线程的概念 进程的存在是由于系统的多任务执行需求&#xff0c;这也要求程序员进…

php基础学习之作用域和静态变量

作用域 变量&#xff08;常量&#xff09;能够被访问的区域&#xff0c;变量可以在常规代码中定义&#xff0c;也可以在函数内部定义 变量的作用域 在 PHP 中作用域严格来说分为两种&#xff0c;但是 PHP内部还定义一些在严格意义之外的一种&#xff0c;所以总共算三种—— 局部…

html从零开始9:javaScript简介,语句、标识符,变量,JavaScript引入到文件【搬代码】

javaScript简介 javaScript语句、标识符 变量 var num 10; var就是固定声明,num就是变量名&#xff0c;10就是变量&#xff1b;<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Comp…

云计算基础-计算虚拟化-CPU虚拟化

CPU指令系统 在CPU的工作原理中&#xff0c;CPU有不同的指令集&#xff0c;如下图&#xff0c;CPU有4各指令集&#xff1a;Ring0-3&#xff0c;指令集是在服务器上运行的所有命令&#xff0c;最终都会在CPU上执行&#xff0c;但是CPU并不是说所有的命令都是一视同仁的&#xf…

Arrays工具类的常见方法总结

一、Arrays.asList( ) 1、作用 Arrays.asList( )可以将一个数组以集合的形式传入一个集合对象。通常用来将一组元素全部添加到集合中。 2、参数及返回值 参数&#xff1a;一组动态参数 返回值&#xff1a;List<T>集合 3、应用举例 List<String> boyListArra…

Mac M2芯片配置PHP环境

Mac M2芯片配置PHP环境 1. XAMPP2. PHPBrew(PHP版本管理)安装php7.4.33版本 3. 直接使用homebrew 安装php环境参考 1. XAMPP 官网地址 https://www.apachefriends.org/ 安装 安装完成 web server打开后&#xff0c;在打开localhost 成功&#xff01; 2. PHPBrew(PHP版本管…

Dynamo读取Revit警告

Hello大家好&#xff01;我是九哥~ 之前看到群里小伙伴经常会问如何去掉Revit重复的图元&#xff0c;有推荐各种插件的&#xff0c;其实的&#xff0c;Revit本身就会提示你有哪些图元是重复的&#xff0c;就在管理选项卡下面的警告里&#xff0c;即查阅警告信息。 点击警告后…

使用html-webpack-plugin对HTML文件进行预处理

原文地址&#xff1a;https://segmentfault.com/a/1190000021518323作者&#xff1a;Fw恶龙本文首发于&#xff1a;思否 一、前言 先整理一波之前和webpack相关的文章: 使用Webpack对CSS文件进行后处理基于Webpack的CSS Sprites实现方案Stylus系列——webpack-spritesmith配合…