拷贝

[元旦小记]C++ 关于结构体拷贝的问题

陌路散爱 提交于 2020-01-12 02:06:50
最近看到一篇关于结构体的复制的微信推文,里面有一段结构体赋值的代码。博主看了以后有所思考,就记录一下。 原文代码,截图留证【手动害怕】 对于malloc 和 free的部分,我们暂时不看,只看这么一句 test1.c = test->c;//成员直接赋值,完成拷贝 其实对于作者构建的这个结构体确实没问题,即使放在多线程环境下也没有问题,但如果子结构体里面存在数组指针呢? 假设这么一种场景: 业务程序需要从内存里面拿到某个ID’的内存块(std::map)存储,然后将用户发送过来的部分信息填入到局部结构体里面后,再回写到全局的内存块里面。 这里我们可能为了减少锁的占用,会在拿到内存块的复制以后,立即释放锁,然后需要回写的时候,再次请求锁。 场景: A线程通过这种办法拿到了全局容器里面的一个结构体的复制,然后释放了锁。 B线程也拿到了这个ID的对应的结构体的一个复制,然后也释放了锁。 A,B都收到了用户发送过来的数据,准备回写内存了(内容不一样,并且修改的内容涉及到指针对应的内存块) 此时会有几种情况发生呢?2种对吧,这里就不写出来了,相信大家都能分析出来。 这里可能还有一种更糟糕的情形: 内存毕竟有限,有增就必须就减,如果在线程会写数据之前,程序的内存调度突然删掉了全局容器里的这个结构体,其结果更难预料,可能正常,可能出现野指针,程序出现未知的行为。 这也就可能是一种非线程安全的设计

【C++】寒假学习-类和对象

回眸只為那壹抹淺笑 提交于 2020-01-11 08:54:50
1. C++内存布局分为几个区域,各自具备什么特点? 在C++中,程序在内存中的存储被分为五个区: 1)、栈区(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 2)、堆区(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。 3)、全局/静态区(static):全局变量和静态变量的存储是 放在一块的,在程序编译时分配 4)、文字常量区:存放常量字符串 5)、程序代码区:存放函数体(类的成员函数、全局函数) 的二进制代码 2. 当定义类时,编译器会为类自动生成哪些函数?这些函数各自都有什么特点? 对于一个空类,C++编译器默认生成四个成员函数:默认构造函数、析构函数、拷贝(复制)构造函数、赋值函数。 1)、默认构造函数(default constructor): 在没有显式提供初始化式时调用的构造函数。它由不带参数的构造函数,或者为所有的形参提供默认实参的构造函数定义。如果定义某个类的变量时没有提供初始化式就会使用默认构造函数。如果用户定义的类中没有显式的定义任何构造函数,编译器就会自动为该类型生成默认构造函数,称为合成的构造函数(synthesized default constructor)。C+

利用PS制作旋转水晶球gif图

被刻印的时光 ゝ 提交于 2020-01-11 06:56:27
起因 临近考试复习数学心态大崩。就弄了一个别的放松一下。 我是借鉴的 PS制作漂亮的旋转水晶球gif动画教程 制作的。 不过我用到PS版本是Photoshop CC 2018,有一些细节与文中不同。 记录一下制作步骤,以后用到的话回来拿。哈哈哈哈 成品效果 第一次做,做的不是特别成功,有些卡顿,奇奇怪怪的,不过大体流程是这样的。 制作步骤 将图片在 Photoshop 中打开 选中背景图,使用 Ctrl + j 快捷键,创建两个图层。为了方便后续图层操作,我们先将背景图隐藏。 选择移动工具。分别选择两个背景图后,按住 Shift 键,将两个图层移动到左右两侧。(注意:选中图层后再按住 Shift ,不然可能会遇到同时移动两个图层等问题) 选择 矩形选框工具 ,在图层1的边界处,选择一块矩形区域,并进行羽化(羽化值可以自己确定),之后按住 Del/Delete 键删除,删除后图层1边界羽化完成。将矩形区域移动到图层1拷贝处,重复操作。 ① 选择矩形选框工具 ② 选择图层 1边界的一块矩形区域后,右键选择羽化。 ③ 完成②后,点击 Del/Delete 删除矩形区域,完成图层1羽化。 ④ 点击图层 1 拷贝,然后将矩形区域移动到图层 1 拷贝的边界 ⑤ 点键盘 Del/Delete 删除。 ⑥ 右键选择区域,选择取消选择。 按住 Shift 调整两个图层位置,让中间部分重合后

python之深浅copy

隐身守侯 提交于 2020-01-11 06:52:36
一.is 与 == python中 == 是比较二者值是否相同,is用来比较二者的内存地址是否相同. n1 = -55 n2 = -55 print(n1 == n2) # True print(id(n1), id(n2)) # 1976371124624 1976371124656 n3 = 'ddd' n4 = 'ddd' print(id(n3), id(n4)) # 2543122508856 2543122508856 print(n3 is n4) # True 二.赋值 2.1 小数据池  两个变量分别进行数值赋值操作是,如(n1 = 'goulonghui', n2 = 'goulonghui),存在小数据池概念 小数据池: int,str在一定范围内,如果两个数值相同,为了节省内存,共用一个内存地址   int范围: -5 - 256    字符串:①单个字母*int(20)存在小数据池,包括20               ②全是字母或者数字,或者字母和数字的任意组合都存在小数据池, 其他都没有         2.2 变量之间相互赋值   python中两个变量之间的相互赋值,则二者共用同一块内存,内存地址相同.(两基友共用一个充气娃娃实例) n3 = [1, 2, 3, [11, 22]] n4 = n3 print(n3, id(n3)) # [1, 2

java提高篇(十九)—–数组之二

∥☆過路亽.° 提交于 2020-01-11 06:44:15
三、性能?请优先考虑数组 在java中有很多方式来存储一系列数据,而且在操作上面比数组方便的多?但为什么我们还需要使用数组,而不是替代它呢?数组与其他种类的容器之间的区别有三个方面:效率、类型和保存基本类型的能力。在java中,数组是一种效率最高的存储和随机访问对象引用序列的方式。 在项目设计中数组使用的越来越少了,而且它确实是没有List、Set这些集合使用方便,但是在某些方面数组还是存在一些优势的,例如:速度,而且集合类的底层也都是通过数组来实现的。 --------这是ArrayList的add()------ public boolean add(E e) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = e; return true; } 下面利用数组和list来做一些操作比较。 一、求和 Long time1 = System.currentTimeMillis(); for(int i = 0 ; i < 100000000 ;i++){ sum += arrays[i%10]; } Long time2 = System.currentTimeMillis(); System.out.println("数组求和所花费时间:" + (time2 - time1) +

ReactNative前置Android环境搭建

纵饮孤独 提交于 2020-01-11 05:12:57
🌴🌴🌴 安装包资源 , 该资源请私信作者获取 1 . 解压文件包 , 运行安装文件 2 . 3 . 4 . 5 . 6 . 7 . 8 . 将解压文件目录下的 android-23.rar , android-24.zip , android-25.rar 文件拷贝至Android安装目录下的 platforms 文件夹下 , 并解压三个文件 . 9 . 将解压文件目录下的 platform-tools-r23.1.0-windows.zip 文件拷贝至Android安装目录根目录下 , 并解压 . 10 . 将 tools_r25.1.7-windows.zip 拷贝至Android安装目录根目录下 , 并解压 11 . 在Android安装目录根目录下新建 build-tools 文件夹 , 并将 build-tools_r23.0.1-windows.zip 、 build-tools_r23.0.2-windows.zip 和 build-tools_r23.0.3-windows.zip 拷贝至该目录下解压 , 并将解压所得文件夹依次重命名为 : 23.0.1 , 23.0.2 , 23.0.3 . 12 . 在Android安装目录根录下新建 extras\android 文件夹 , 并将 android_m2repository_r40.zip 文件和 support

Python赋值、浅拷贝、深拷贝的区别

非 Y 不嫁゛ 提交于 2020-01-11 03:39:11
一、赋值 str例子 >>> a = 'hello' >>> b = 'hello' >>> c = a >>> [id(x) for x in (a,b,c)] [42654216, 42654216, 42654216] a,b,c三者地址一样,相当于a=b=c。赋值系统先给变量或对象(这里的hello)分配了内存,然后将地址赋给a,b,c。所以他们的地址是相同的。 >>> a = 'world' >>> [id(x) for x in (a,b,c)] [42654384, 42654216, 42654216] >>> print(a,b,c) world hello hello 这时只有a的地址和值变了,但是b,c地址和值都没有变。因为str的不可变性,a要重新赋值则需重新开辟内存空间,所以a的值改变,a指向的地址改变。b, c由于'hello'的不变性,不会发生改变。 list例 >>> a = ['hello'] >>> b = ['hello'] >>> c = a >>> [id(x) for x in (a,b,c)] [42670920, 42671816, 42670920] 但是这种情况却不一样了,a和b的地址不同。为何? 因为str是不可变的,所以同样是'hello'只有一个地址,但是list是可变的,所以必须分配两个地址。 >>> a[0] =

用递归实现文件夹拷贝以及文件拷贝

别说谁变了你拦得住时间么 提交于 2020-01-10 23:35:13
异常部门我是直接处理的,如果嫌麻烦的话也可向外抛出 闲话不多说,直接上代码。。。 package com.ListFile; import java.io.*; /** * 统计文件个数 */ public class CopyFile { //定义一个外部变量,用于存放拷贝文件时穿件新的文件夹名称 public static String newFileName; public static String address = "D";//定义拷贝地址的盘符 /** * main方法 * @param args */ public static void main(String[] args) { File file = new File("F:/test"); //传入想拷贝的文件的路径 count(file); } /** * 递归实现拷贝 * @param file */ public static void count(File file){ if (null != file && file.exists()) {//递归头 //递归体 if (file.isFile()) {//如果是文件,直接拷贝 copy(file.getAbsolutePath(),newFileName); }else{ for (File f : file.listFiles()){/

linux-零拷贝技术

六月ゝ 毕业季﹏ 提交于 2020-01-10 22:26:31
content: 1.0 用户态内核态之间切换 2.0 文件发送所经历的文件拷贝 3.0 文件发送经历的文件拷贝(优化)----零拷贝 4.0 零拷贝使用场景----kafka 用户态内核态之间切换 用户态切换至内核态出现场景:系统调用/中断处理/异常处理 用户态切换至内核态原因:用户态下无法访问或者处理内核地址空间下的数据,用户空间程序0-3G无法执行内核代码,不能直接调用内核函数(内核函数驻留在受保护的地址空间上)。 切换过程: a) 触发int &0x80(int 软中断指令、0x80立即数参数) b) 切换内核态并执行128号异常中断程序。 c) 128号异常终端程序用来执行系统调用,具体实现:system_call()使用具体的系统调用(利用系统调用号),通过eax寄存器传递系统调用号至内核,使用ebx、ecx、edx、esi、edi等寄存器传递参数,超过5个参数时创建堆栈,用独立的寄存器存储该堆栈地址,将参数传递至内核。 文件传输所经历的文件拷贝次数 第一次:系统调用read方法(用户态---->内核态),底层使用DMA读取磁盘文件并存储至内核地址空间读取缓冲区。 第二次:因应用程序无法读取受保护的内核地址空间数据,所以将该数据拷贝至用户地址空间(内核态---->用户态)缓冲区,read调用返回。 第三次:调用socket的send方法(用户态---->内核态)

Python——赋值、浅拷贝、深拷贝

ⅰ亾dé卋堺 提交于 2020-01-10 20:14:00
  和很多语言一样,Python中也分为简单赋值、浅拷贝、深拷贝这几种“拷贝”方式。   在学习过程中,一开始对浅拷贝理解很模糊。不过经过一系列的实验后,我发现对这三者的概念有了进一步的了解。   一、赋值    赋值算是这三种操作中最常见的了,我们通过一些例子来分析下赋值操作:    str例 >>> a = 'hello' >>> b = 'hello' >>> c = a >>> [id(x) for x in a,b,c] [4404120000, 4404120000, 4404120000]   由以上指令中,我们可以发现a, b, c三者的地址是一样的。所以以上赋值的操作就相当于c = a = b = 'hello'。   赋值是系统先给一个变量或者对象(这里是'hello')分配了内存,然后再将地址赋给a, b, c。所以它们的地址是相同的。    list例 >>> a = ['hello'] >>> b = ['hello'] >>> c = a >>> [id(x) for x in a,b,c] [4403975952, 4404095096, 4403975952]   但是这种情况却不一样了,a和b的地址不同。为何?    因为str是不可变的,所以同样是'hello'只有一个地址,但是list是可变的,所以必须分配两个地址。   这时