指针

智能指针

岁酱吖の 提交于 2020-03-05 07:27:53
title: 智能指针 date: 2018-04-02 15:21:32 categories: C/C++ tags: 指针 为什么使用动态指针? 在C++中,动态内存的管理是通过一对运算符来完成的: new: 在动态内存中为对象分配空间并返回一个指向该对象的指针,同时可以对这个对象初始化。 delete: 接受一个动态对象的指针,销毁该对象并释放与之关联的内存。 这样动态内存的使用就很容易出现问题: 忘记释放内存(delete)就会产生内存泄漏的问题。 过早释放内存(在还有指针引用该内存的时候就释放了它)就会产生引用非法内存的指针。 为了防止出现这种情况,更容易更安全地使用动态内存, 自C++11开始提供了两种智能指针类型来管理动态对象。 什么是智能指针? 智能指针是存储指向动态分配(堆)对象指针的类。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。 智能指针的原理是什么? 资源分配即初始化RAII(Resource Acquisition Is Initialization):RAII 的做法是使用一个对象,在其构造时获取资源,在对象生命期控制对资源的访问使之始终保持有效,最后在对象析构的时候释放资源。 定义一个类来封装资源的分配和释放,在构造函数完成资源的分配 和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放。

Slotted-Page简介与定长记录的SSD页式存储

六眼飞鱼酱① 提交于 2020-03-05 03:47:45
首先介绍下传统硬盘的一种动态分配空间的页式存储数据结构:Slotted-Page structure(分槽页结构) 它具有以下特点: 1. Records(记录)顺序存储(从块的头部/尾部) 2. 有顺序添加的指针指向每条记录的起始位置(从块的尾部/头部) 3. 记录可在页中移动位置 如图所示,页尾存有指向每一个记录起始位置的指针。 当有一条新纪录插入时,它会顺序加到图中52的后面,同时尾部也多加一个指向这条新纪录的指针。 当有一条记录删除时,系统会释放该空间,移除相关的信息指针,后续记录可往前填补这个空隙。 假设我们的数据库系统只用定长的记录(fixed length records)存储。对于传统硬盘来说,上述的slotted-page方法就是一种可行的方案。 如果要用SSD来存储,该如何设计呢? 首先简单介绍下SSD: 其中的闪存(flash)分为一个或多个dies(chips),每个die又分为4 * 2018 = 8192 blocks(块),每块中包含32-64页,而页就是读写的最小单元。 限制(Constraints): Erase-Constraint:除非已擦除该页所在的块,否则无法覆盖写(over-written)该页 Write-Constraint:一个块中的页内必须从低地址往高地址顺序写 Wear-Constraint:一个块被擦除的次数是有限制的

JVM学习【二】---对象的内存布局

两盒软妹~` 提交于 2020-03-05 02:29:15
二、对象(实例)的内存布局 1.对象的创建 虚拟机遇到一个new指令 检查这个指令的参数是否能在常量池中定位到一个类的符号引用 检查这个符号引用代表的类是否已经被加载、解析、初始化过。 如果没有,则执行类加载过程。(如果有,直接为新对象分配内存) 类加载检查通过后,vm为新生对象分配内存。(对象所需要的内存大小,在类加载完成后就能完全确定) 根据不同情况选取,内存分配策略:1)指针碰撞。2)空闲列表。(采取哪种分配方式由内存是否规整决定,内存是否规整由GC策略决定) 指针碰撞:堆中的内存是足够规整的,占用中内存和空闲内存以一个指针为分割,各占内存的一边。此时分配内存,只需要移动指针到对象大小的距离。这种分配方式叫做指针碰撞。 空闲列表:堆中的内存不规整,无法通过一个指针去标识,vm必须维护一个空闲内存列表,在分配时找出一块足够大的内存去分配,并更新列表记录,这种分配方式叫做空闲列表。 在TLAB中分配空间。(TLAB本地线程分配缓存,用于解决并发问题,线程1给A分配内存,刚分配完,指针还没修改或是列表还没更新,线程2又使用了刚刚的指针分配给B了内存,为了保证内存分配的安全,每个线程都预分配了一个独立的内存缓冲区,每个线程分配内存时,都在自己的缓冲区内存里分配,等缓冲区内的内存用完了,再使用同步锁定保证原子性。) 内存分配完成后(指针移位,列表同步),已分配的内存空间都初始化为0

leetcode 15.三数之和

﹥>﹥吖頭↗ 提交于 2020-03-04 23:04:52
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。 注意:答案中不可以包含重复的三元组。 示例: 给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ] 解题思路: 三个数之和,要么是依次遍历数组三个数相加看是否等于0,但是这种方法算法复杂度等于0(n^3),有点复杂。 还有一种思路是先对数组进行一次排序,然后找一个固定值,nums[i],然后设置两个指针,left=i+1,right = nums.length -1,两个指针一起循环,如果三个数的和等于0那就存放,如果大于0,就让尾指针 right 向前走,如果小于0,就让头指针 left 向前走。(这块建议自己在纸上画一画,先对数组排序,然后固定一个值,从设置头尾指针进行遍历) var threeSum = function(nums) { //设置变量 let result = [] let left //头指针 let right //尾指针 let fixedValue //固定值 //排序 nums.sort( (a,b) => { return a-b }) //判断数组内的元素是否都大于0,或者都小于0

C语言-怎么找115资源

眉间皱痕 提交于 2020-03-04 22:21:54
C 语言的起源与发展 C 语言的开发 Dennis M. Ritchie Bell Labs/Lucent Technologies Murray Hill, NJ 07974 USA 摘要 C 编程语言是在 1970 年代早期作为初创的 Unix 操作系统的系统实现语言而设计的。起源于无类型的 BCPL 语言,它发展出了类型结构;它建立在一个小机器上、作为改善其贫乏的编程环境的工具,它现在已经成为占主导地位的语言之一。本文研讨它的演变。   注意: *Copyright 1993 Association for Computing Machinery, Inc. This electronic reprint made available by the author as a courtesy. For further publication rights contact ACM or the author. This article was presented at Second History of Programming Languages conference, Cambridge, Mass., April, 1993. It was then collected in the conference proceedings: History of Programming

C++ 智能指针 auto_ptr 和 shared_ptr

空扰寡人 提交于 2020-03-04 17:19:04
首先,如果你不知道什么是智能指针,请先移步: C++智能指针简单剖析 1.auto_ptr 1 #ifndef AUTO_PTR_H 2 #define AUTO_PTR_H 3 4 template<typename T> 5 class auto_ptr 6 { 7 public : 8 //使用explicit关键字避免隐式转换 9 explicit auto_ptr(T* p=0); 10 ~auto_ptr(); 11 12 //使用另一个类型兼容的auto_ptr来初始化一个新的auto_ptr 13 template<typename U> 14 auto_ptr(auto_ptr<U>& rhs); 15 16 template<typename U> 17 auto_ptr<T>& operator=(auto_ptr<U>& rhs); 18 19 T& operator*() const; 20 T* operator->() const; 21 22 //返回原始对象的指针 23 T* get() const; 24 //放弃指针的所有权 25 T* release(); 26 //删除原有指针并获得指针p的所有权 27 void reset(T* p=0); 28 29 private: 30 T* pointee; 31 }; 32 33

第二讲 auto_ptr智能指针

六月ゝ 毕业季﹏ 提交于 2020-03-04 17:18:30
auto_ptr 不可被共享,只能指向一个对象 auto_ptr在构造时获取对某个对象的所有权(ownership),在析构时释放该对象。我们可以这样使用auto_ptr来提高代码安全性: int* p = new int(0); auto_ptr<int> ap(p); 从此我们不必关心应该何时释放p, 也不用担心发生异常会有内存泄漏。 这里我们有几点要注意: 1) 因为auto_ptr析构的时候肯定会删除他所拥有的那个对象,所有我们就要注意了,一个萝卜一个坑,两个auto_ptr不能同时拥有同一个对象。像这样: int* p = new int(0); auto_ptr<int> ap1(p); auto_ptr<int> ap2(p); 因为ap1与ap2都认为指针p是归它管的,在析构时都试图删除p, 两次删除同一个对象的行为在C++标准中是未定义的。所以我们必须防止这样使用auto_ptr. 2) 考虑下面这种用法: int* pa = new int[10]; auto_ptr<int> ap(pa); 因为auto_ptr的析构函数中删除指针用的是delete,而不是delete [],所以我们不应该用auto_ptr来管理一个数组指针。 3) 构造函数的explicit关键词有效阻止从一个“裸”指针隐式转换成auto_ptr类型。 4) 因为C+

boost库:智能指针

心已入冬 提交于 2020-03-04 16:53:05
1. C98里的智能指针 std::auto_ptr ,本质上是一个普通的指针,通过地址来访问你一个动态分配的对象,初始化时需要传递一个由new操作符返回的对象地址。 std::auto_ptr的析构函数会调用delete操作符,释放掉其包含的对象内存。 智能指针的原理基于一个常见的习语:RAII(资源申请即初始化)。智能指针确保在任何情况下,动态分配的内存都能够得到正确释放,包括程序因为 异常而中断,原本用于释放内存的代码被跳过的场景。用一个动态分配的对象的地址来初始化智能指针,因为析构函数总是会被执行的,则包含的内存就会被释放。 2. 作用域指针 一个作用域指针独占一个动态分配的对象。其类名为:boost::scoped_ptr,一个作用域指针不能传递它所包含的对象的所有权到另一个作用域指针。作用域指针只是简单保存和独占一个内存地址,在不需要所有权传递的时候应该优先使用boost::scoped_ptr。 由于boost::scoped_ptr的析构函数中使用delete操作符来释放所包含的对象,因此boost::scoped_ptr不能用动态分配的数组来做初始化。 3. 作用域数组 与作用域指针相似。不同在于:作用域数组的析构函数使用delete[]操作符来释放所包含的对象,因此该操作符只能用于数组对象,所以作用域数组必须通过动态分配的数组来初始化。 4. 共享指针

Boost学习笔记-智能指针

ぐ巨炮叔叔 提交于 2020-03-04 16:52:47
1. 智能指针 scoped_ptr 只在作用域内生效,离开作用域既释放资源,不能复制和赋值。类似于标准库的auto_ptr,但它相对于auto_ptr的优势在于,他的要求更严格,使用起来更安全。auto_ptr拥有转移语义,当使用了赋值和复制操作时可能操作未定义行为。 scoped_array scoped_array 的数组形式,区别在于他管理的对象是用new []分配,同时释放时用delete[],能正确的释放数组对象。不能用*和->操作符,支持[]操作符方式解引用。scoped_array不推荐使用,因为使用麻烦,可以用vector代替。 shared_ptr shared_ptr是一个引用计数型智能指针,当计数为0时自动释放管理的资源。支持*和->指针操作行为,提供隐式bool类型转换用于指针有效性判断。通过get()方法可以获取原始指针。 shared_ptr有两个专门的函数来检查引用计数。unique()指示该指针是否是对象的唯一管理者。use_count()指示对象正在由多少智能 指针引用。 shared_ptr支持比较运算,基于内部保持的指针实现。 通过make_shared<T>()函数可以使用工厂创建share_ptr对象,而省去显示的new调用。 shared_ptr支持定制删除器,可以指定share_ptr管理的对象在析构时自动调用删除器

[zz]Boost智能指针——scoped_ptr

非 Y 不嫁゛ 提交于 2020-03-04 16:50:51
boost::scoped_ptr 和 std::auto_ptr 非常类似,是一个简单的智能指针,它能够保证在离开作用域后对象被自动释放。下列代码演示了该指针的基本应用: #include <string> #include <iostream> #include <boost/scoped_ptr.hpp> class implementation { public : ~implementation() { std::cout << "destroying implementation/n" ; } void do_something() { std::cout << "did something/n" ; } }; void test() { boost::scoped_ptr<implementation> impl( new implementation()); impl->do_something(); } void main() { std::cout<< "Test Begin ... /n" ; test(); std::cout<< "Test End./n" ; } 该代码的输出结果是: Test Begin ... did something destroying implementation Test End. 可以看到:当 implementation