cpp primer笔记090-动态内存

news2024/11/18 11:30:26
  1. shared_ptr和unique_ptr都支持的操作,加上shared_ptr独有的操作
    ![[Pasted image 20230923103844.png]]

![[Pasted image 20230923103855.png]]

  1. 每个shared_ptr都有一个关联的计数器,通常称其为引用计数,当调用了shared_ptr的构造函数时就会递增,当调用析构函数时就会递减,一旦一个shared_ptr的计数器为0的时候,它就会自动释放自己所管理的对象。
    #include <iostream>
    #include <fstream>
    #include <array>
    #include <vector>
    #include <string>
    #include <exception>
    #include <algorithm>
    #include <stack>
    #include <deque>
    #include <numeric>
    #include <memory>
    int main()
    {
    	std::shared_ptr<int> ptr1 = std::make_shared<int>(10);
    	std::cout << ptr1.unique() << " " << ptr1.use_count() << std::endl;
    	std::shared_ptr<int> ptr2 = std::make_shared<int>(10);
    	std::cout << ptr1.unique() << " " << ptr1.use_count() << std::endl;
    std::shared_ptr<int> ptr3(ptr1);
    std::cout << ptr1.unique() << " " << ptr1.use_count() << std::endl;
    

}
cpp
1 1
1 1
0 2

```
  1. 如果想让STL的容器产生类似于shared_ptr指针的效果,可以进行下面的操作:(如果一个shared_ptr指向的对象的引用次数为0,则该对象会被销毁)

    #include <iostream>
    #include <fstream>
    #include <array>
    #include <vector>
    #include <string>
    #include <exception>
    #include <algorithm>
    #include <deque>
    #include <numeric>
    #include <memory>
    #include <initializer_list>
    #include <exception>
    class StrBlob
    {
    public:
    	typedef std::vector<std::string>::size_type size_type;
    	StrBlob() :
    		data(std::make_shared<std::vector<std::string>>()) {};
    	StrBlob(std::initializer_list<std::string> il) :
    		data(std::make_shared<std::vector<std::string>>(il)) {};
    	StrBlob(std::vector<std::string> vec) :
    		data(std::make_shared<std::vector<std::string>>(vec)) {};
    	~StrBlob() = default;
    
    	size_type size() const;
    	void push_back(const std::string& t);
    	void pop_back();
    	std::string front() const;
    	std::string back() const;
    	auto cbegin() -> decltype(std::cbegin(std::vector<std::string>()));
    	auto cend() -> decltype(std::cend(std::vector<std::string>()));
    private:
    	std::shared_ptr<std::vector<std::string>> data;
    	void check(size_type i, const std::string& msg) const throw(const std::string&);
    };
    std::vector<std::string>::size_type StrBlob::size() const
    {
    	return data->size();
    }
    
    void StrBlob::push_back(const std::string& t)
    {
    	data->push_back(t);
    }
    
    void StrBlob::pop_back()
    {
    	data->pop_back();
    }
    
    std::string StrBlob::front() const
    {
    	check(0, "front on empty StrBlob");
    	return data->front();
    }
    
    std::string StrBlob::back() const
    {
    	check(0, "back on empty StrBlob");
    	return data->back();
    }
    
    void StrBlob::check(std::vector<std::string>::size_type i, const std::string& msg) const throw(const std::string&)
    {
    	if (i >= data->size())
    	{
    		throw std::out_of_range(msg);
    	}
    }
    
    auto StrBlob::cbegin() -> decltype(std::cbegin(std::vector<std::string>()))
    {
    	return this->data->cbegin();
    }
    
    auto StrBlob::cend() -> decltype(std::cend(std::vector<std::string>()))
    {
    	return this->data->cend();
    }
    
    int main()
    {
    	StrBlob str1({ "123", "fsdf","zcxv" });
    	StrBlob str2 = str1;
    	str1.push_back("sdfsdfz");
    	str1.~StrBlob();
    	std::ostream_iterator<std::string> os(std::cout, " ");
    	std::for_each(str2.cbegin(), str2.cend(), [&os](std::string val) { os = val; });
    	return 0;
    }
    
    123 fsdf zcxv sdfsdfz
    
  2. 智能指针不允许进行内置指针到智能指针间的隐式转换,只能显示转换。下面是shared_ptr和new结合使用的各种函数

    #include <iostream>
    #include <fstream>
    #include <array>
    #include <vector>
    #include <string>
    #include <exception>
    #include <algorithm>
    #include <deque>
    #include <numeric>
    #include <memory>
    #include <initializer_list>
    #include <exception>
    std::shared_ptr<int> clone(int p)
    {
    	//return new int(p);不能隐式转换
    	return std::shared_ptr<int>(new int(p));
    }
    int main()
    {
    	std::shared_ptr<int> ptr1;
    	std::shared_ptr<double> ptr2(new double(42));//可以通过构造函数转换
    	//std::shared_ptr<int> ptr3 = new int(1024);不能隐式转换
    	return 0;
    }
    

    ![[Pasted image 20230923144221.png]]

    ![[Pasted image 20230923153455.png]]

    ![[Pasted image 20230923161047.png]]

  3. 不要混用普通指针和智能指针,尽量都是用智能指针,如果混用二者会产生以下未定义行为。智能指针相对于普通指针的区别有当函数使用智能指针的时候,如果抛出异常,则栈解退的时候会自动调用析构函数释放内存,而使用普通指针的时候则不会delete掉

    void process(std::shared_ptr<int> ptr)
    {
    	;
    }
    int main()
    {
    	std::shared_ptr<int> p(new int(42));
    	process(p);
    	int i = *p;
    	std::cout << i << std::endl;
    	int* x(new int(1024));
    	//process(x); 不能将int*显式转换为一个shared_ptr<int>()类型的指针
    	process(std::shared_ptr<int>(x));//如果将x显式类型转换,则可能导致x的内存被释放
    	int j = *x;//未定义行为:x是一个悬空指针!
    	std::cout << j << std::endl;
    	return 0;
    }
    
    42
    -572662307
    
  4. unique_ptr操作,一般情况下是不允许拷贝unique_ptr,但是如果从函数返回一个unique_ptr值或者返回一个局部对象拷贝的情况下是允许的。
    ![[Pasted image 20230923154021.png]]

![[Pasted image 20230923161112.png]]

	#include <vector>
	#include <string>
	#include <exception>
	#include <algorithm>
	#include <deque>
	#include <numeric>
	#include <memory>
	#include <initializer_list>
	#include <exception>
	std::unique_ptr<std::string> clone1(std::string str)
	{
		return std::unique_ptr<std::string>(new std::string(str));
	}
	std::unique_ptr<std::string> clone2(std::string str)
	{
		std::unique_ptr<std::string> ret(new std::string(str));
		return ret;
	}
	int main()
	{
		std::unique_ptr<std::string> ptr1(new std::string("sjkdfskdf"));
		std::unique_ptr<std::string> ptr2(ptr1.release());
		std::unique_ptr<std::string> ptr3(new std::string("kxcnsd"));
		std::cout << *ptr2 << std::endl;
		ptr2.reset(ptr3.release());
		std::cout << *ptr2 << std::endl;
		return 0;
	}
  1. weak_ptr的一些操作:
    ![[Pasted image 20230923160922.png]]

  2. 由于分配的内存并不是一个数组类型,因此不能对动态数组调用begin和end函数,也不能用范围for语句来处理动态数组中的元素,我们所说的动态数组并不是数组类型

  3. 指向数组的unique_ptr支持一下操作,由于shared_ptr不支持通过[]访问的操作,因此需要使用get函数。
    ![[Pasted image 20230923163322.png]]

	#include <iostream>
	#include <fstream>
	#include <array>
	#include <vector>
	#include <string>
	#include <exception>
	#include <algorithm>
	#include <deque>
	#include <numeric>
	#include <memory>
	#include <initializer_list>
	#include <exception>
	int main()
	{
		std::unique_ptr<int[]> up(new int[10]);
		std::shared_ptr<int> sp(new int[10], [](int* p) {delete[] p; });
		for (size_t i = 0; i != 10; ++i)
		{
			up[i] = i;
			*(sp.get() + i) = 2 * i;
		}
		for (size_t i = 0; i < 10; ++i)
		{
			std::cout << up[i] << "/" << *(sp.get() + i) << " ";
		}
		return 0;
	}
  1. allocate的使用:
    ![[Pasted image 20230923170327.png]]
	#include <iostream>
	#include <fstream>
	#include <array>
	#include <vector>
	#include <string>
	#include <exception>
	#include <algorithm>
	#include <deque>
	#include <numeric>
	#include <memory>
	#include <initializer_list>
	#include <exception>
	int main()
	{
		int n;
		std::allocator<std::string> alloc;//可以分配string内存的allocator对象
		std::cin >> n;
		auto const start = alloc.allocate(n);//分配十个内存,start是指向该内存开头的指针
		auto end = const_cast<decltype(alloc.allocate(n))>(start);//end即构造完成的内存的下一个位置
		alloc.construct(end++, 10, 'c');//构造一个含有10个c的字符串
		alloc.construct(end++, "sdfksd");//构造一个sdfksd的字符串
		for (auto it = start; it != end; ++it)
		{
			std::cout << *it << " ";//输出已经构造的空间的字符串
		}
		std::cout << std::endl;
		alloc.destroy(--end);//重置一个已经构造的空间,但是并不会销毁
		for (auto it = start; it != end; ++it)
		{
			std::cout << *it << " ";
		}
		alloc.deallocate(start, n);//销毁所有已分配的空间
		return 0;
	}
	5
	cccccccccc sdfksd
	cccccccccc

![[Pasted image 20230923171456.png]]在这里插入图片描述

	#include <iostream>
	#include <fstream>
	#include <array>
	#include <vector>
	#include <string>
	#include <exception>
	#include <algorithm>
	#include <deque>
	#include <numeric>
	#include <memory>
	#include <initializer_list>
	#include <exception>
	int main()
	{
		std::allocator<int> a,b;
		auto beginPtrA = a.allocate(10);
		auto beginPtrB = b.allocate(10);
		std::uninitialized_fill_n(beginPtrA, 10, 5);
		for (size_t i = 0; i < 10; ++i)
		{
			std::cout << *(beginPtrA + i) << " ";
		}
		std::cout << std::endl;
		std::uninitialized_copy_n(beginPtrA, 10, beginPtrB);
		for (size_t i = 0; i < 10; ++i)
		{
			std::cout << *(beginPtrA + i) << " ";
		}
		return 0;
	}
5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5
  1. 智能指针shared_ptr和unique_ptr重载删除器,都可以用普通函数,仿函数和未捕获任何类型的lambda表达式,但是unique需要传递一个函数指针
    #define _CRT_SECURE_NO_WARNINGS 1
    #include <iostream>
    #include <string>
    #include <memory>
    #include <deque>
    #include <vector>
    #include <algorithm>
    #include <functional>
    void deleter(int* x)
    {
        std::cout << "普通函数删除器" << std::endl;
        delete[] x;
    }
    class Deleter
    {
    public:
        void operator() (int* x) {
            std::cout << "仿函数删除器" << std::endl;
            delete[] x;
        }
    };
    
    int main() 
    {
        std::shared_ptr<int> shPtr1(new int[5], deleter);
        std::shared_ptr<int> shPtr2(new int[2], std::function<void(int*)>(Deleter()));
        std::shared_ptr<int> shPtr3(new int[7], [](int* x) {
            std::cout << "lambda表达式删除器" << std::endl;
        delete[] x;
            });
        std::unique_ptr<int[], std::function<void(int*)>> unPtr1(new int[5], deleter);
        std::unique_ptr<int[], std::function<void(int*)>> unPtr2(new int[6], std::function<void(int*)>(Deleter()));
        std::unique_ptr<int[], std::function<void(int*)>> unPtr3(new int[7], [](int* x) {
            std::cout << "lambda表达式删除器" << std::endl;
        delete[] x;
            });
        return 0;
    }
    
    

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【2023年11月第四版教材】第19章《配置与变更管理》(合集篇)

第19章《配置与变更管理》&#xff08;合集篇&#xff09; 1 章节内容2 配置管理3 变更管理4 项目文档管理 1 章节内容 【本章分值预测】本章内容90%和第三版教材内容一样的&#xff0c;少部分有一些变化&#xff0c;特别是变更涉及的人员及职责&#xff0c;预计选择题考3分&a…

Python如何实现数据驱动的接口自动化测试

大家在接口测试的过程中&#xff0c;很多时候会用到对CSV的读取操作&#xff0c;本文主要说明Python3对CSV的写入和读取。下面话不多说了&#xff0c;来一起看看详细的介绍吧。 1、需求 某API&#xff0c;GET方法&#xff0c;token,mobile,email三个参数 token为必填项mobil…

Connect to 127.0.0.1:1080 [/127.0.0.1] failed: Connection refused: connect

报错信息 A problem occurred configuring root project CourseSelection. > Could not resolve all artifacts for configuration :classpath.> Could not resolve com.android.tools.build:gradle:3.6.1.Required by:project :> Could not resolve com.android.tool…

力扣第101题 c++ 递归 迭代 双方法 +注释 ~

题目 101. 对称二叉树 简单 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false提示&a…

点读笔背后的神秘力量,究竟是如何实现即时识别的?

点读笔是一种智能学习工具&#xff0c;通过与印刷物或电子设备配合使用&#xff0c;将文字、图片或声音转化为可听、可读、可学习的内容。它的核心功能是识别并解析特定标识&#xff08;如二维码、条形码&#xff09;或区域内的信息&#xff0c;并提供相应的语音、文字或图像反…

docker swarm安装指导

SWARM部署DOCKER集群 1. 简介............................................................................................................................ 3 2. 部署准备.........................................................................................…

15040-2021 工作测光标准灯泡 学习记录

声明 本文是学习GB-T 15040-2021 工作测光标准灯泡.pdf而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件规定了工作测光标准灯(下文在不会引起误解时简称为"标准灯”或“灯")的分类、 一般要求、 技术要求和试验方法&#xff…

详解链表oJ<反转链表,链表的中间节点及链表的回文>

hello&#xff0c;大家好&#xff0c;这里是Dark FlameMaster,今天和大家分享的是有关数据结构链表的几道题目&#xff0c;链表的中间节点&#xff0c;反转链表及判断链表是否为回文结构&#xff0c;放在一起讲解会印象更加深刻。 文章目录 一&#xff0c;链表的中间节点二&…

C#,数值计算——数据建模FGauss的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public class FGauss : MultiFuncd { public void funk(double x, double[] a, ref double y, double[] dyda) { int na a.Length; y 0.0; for (int …

吃鸡达人专享!提高战斗力,分享干货,查询装备皮肤,保护账号安全!

大家好&#xff01;作为专业吃鸡行家&#xff0c;我将为您带来一些热门话题和实用内容&#xff0c;帮助您提升游戏战斗力&#xff0c;分享顶级游戏作战干货&#xff0c;并提供便捷的作图工具和查询服务。让我们一起享受吃鸡的乐趣&#xff01; 首先&#xff0c;我要推荐一款绝地…

CleanMyMacX 永久版下载激活码破解版

CleanMyMac X最新破解版V4.9.2是一款出色的Mac 系统垃圾清理程序。 该软件具有强大的垃圾清理功能&#xff0c;可以释放数 GB 的空间&#xff0c;让您的 Mac 焕然一新。 带有激活码的完整破解版 CleanmyMac 可加速您的 Mac 设备。 此外&#xff0c;cleanmymac还能帮助您从 Mac…

2023最新ICP备案查询系统源码 附教程 Thinkphp框架

2023最新ICP备案查询系统源码 附教程 thinkphp框架 本系统支持网址备案&#xff0c;小程序备案&#xff0c;APP备案查询&#xff0c;快应用备案查询 优势&#xff1a; 响应速度快&#xff0c;没有延迟&#xff0c;没有缓存&#xff0c;数据与官方同步 源码下载&#xff1a;ht…

Puppeteer基础知识(一)

Puppeteer基础知识&#xff08;一&#xff09; Puppeteer基础知识&#xff08;一&#xff09;一、简介二、其他一些自动化测试工具三、Puppeteer常用命令四、常见问题解决&#xff1a; 一、简介 Puppeteer 是一个强大而灵活的工具&#xff0c;可以用于网页爬虫、自动化测试、性…

大数据Doris(六):编译 Doris遇到的问题

文章目录 编译 Doris遇到的问题 一、js_generator.cc:(.text+0xfc3c): undefined reference to `well_known_types_js’

华为云新开源低代码引擎 TinyEngine

在当今数字化飞速发展的时代&#xff0c;企业对高效、敏捷的应用程序需求日益旺盛。为了满足这一需求&#xff0c;越来越多的低代码开发平台开始涌现。这些平台通过提供简单易用的开发工具和优化后的开发流程&#xff0c;帮助开发者快速构建高质量、可重复使用的应用程序&#…

Suricata + Wireshark离线流量日志分析

Suricata 环境搭建&#xff1a;基于Ubuntu坏境下的Suricata坏境搭建_奈何&#xff20;_&#xff20;的博客-CSDN博客 suricata&#xff1a;监控日志 wireshark:监控流量 同时使用需要降噪&#xff0c;因为规则有许多重叠 题目及要求我打包上传了&#xff0c;有需要的同学自…

十一工具箱流量主小程序源码

无授权&#xff0c;去过滤机制版本 看到网上发布的都是要授权的 朋友叫我把他去授权&#xff0c;能用就行 就把过滤去了 这样就不用授权 可以免费使用 白嫖党专属 一切接口可用&#xff0c;无需担心不能用 授权者不关站一直可以用 源码下载&#xff1a;https://download.csdn.…

彻底理解浏览器cookie策略

cookie介绍 为什么存在cookie&#xff1f; &#xff08;1&#xff09;cookie存在的原因 因为http请求是无状态的&#xff0c;同一个用户从浏览器向A服务器发送两次请求&#xff0c;A服务器无法判断这两次请求是否是同一个用户。所以&#xff0c;浏览器提供了客户端携带cooki…

threejs 透明贴图,模型透明,白边

问题 使用Threejs加载模型时&#xff0c;模型出现了上面的问题。模型边缘部分白边&#xff0c;或者模型出现透明问题。 原因 出现这种问题是模型制作时使用了透明贴图。threejs无法直接处理贴图。 解决 场景一 模型有多个贴图时&#xff08;一个透贴和其他贴图&#xff0…

互联网Java工程师面试题·Redis篇·第一弹

目录 1、什么是 Redis? 2、Redis 优势 3、Redis 与其他 key-value 存储有什么不同&#xff1f; 4、Redis 的数据类型&#xff1f; 5、使用 Redis 有哪些好处&#xff1f; 6、Redis 相比 Memcached 有哪些优势&#xff1f; 7、Memcache 与 Redis 的区别都有哪些&#xf…