前驱和后继指针是为了将结点串在双向链表中,hnext 指针是为了将结点串在散列表的拉链中。 Redis 有序集合 在跳表那一节,讲到有序集合的操作时,我稍微做了些简化。...我来具体分析一下,为什么这段代码会按照这样顺序来打印。 每次调用 put() 函数,往 LinkedHashMap 中添加数据的时候,都会将数据添加到链表的尾部。...散列表这种数据结构虽然支持非常高效的数据插入、删除、查找操作,但是散列表中的数据都是通过散列函数打乱之后无规律存储的。也就说,它无法支持按照某种顺序快速地遍历数据。...、 课后思考 今天讲的几个散列表和链表结合使用的例子里,我们用的都是双向链表。如果把双向链表改成单链表,还能否正常工作呢?为什么呢?...在删除一个元素时,虽然能 O(1) 的找到目标结点,但是要删除该结点需要拿到前一个结点的指针,遍历到前一个结点复杂度会变为 O(N),所以用双链表实现比较合适。
因为我们的链表是双向链表,双向链表可以通过前驱指针O(1)时间复杂度获取前驱结点,所以在双向链表中,删除结点只需要O(1)的时间复杂度。...hash表这种数据结构虽然支持非常高效的数据插入、删除、查找操作,但hash表中的数据都是通过hash函数打乱之后无规律存储的。也就说,它无法支持按照某种顺序快速地遍历数据。...如果把双向链表改成单链表,还能否正常工作呢?...在删除一个元素时,虽然能 O(1) 的找到目标结点,但是要删除该结点需要拿到前一个结点的指针,遍历到前一个结点复杂度会变为 O(N),所以用双链表实现比较合适。...查找按照积分从小到大排名在第 x 位到第 y 位之间的猎头 ID 列表 以积分排序构建一个跳表,再以猎头 ID 构建一个散列表: 1)ID 在散列表中所以可以 O(1) 查找到这个猎头; 2)积分以跳表存储
曾经以为C语言已经深入骨髓,融入血液,直到看到一到这样的面试题,才发现学海无涯: ? 请问代码中,第10、11和12行,分别会输出什么?...这个结果的分析如下: 1,首先,a的值是0x100,这个没什么毛病。 2,其次,p的值是0xbffa12e4是变量a的地址,直接输出,也没什么毛病。...毕竟,第8行的代码就是让变量a的地址,存放到指针p里面。...3,再其次,*p的输出结果就有点不可理解了,按道理,*p值得就是p所指向的目标,也就是变量a,那应该输出 0x100 才对,但结果却依然是a的地址,仿佛目标引用符 * 不起作用了?...的! 造成指针的目标引用符失效的原因,在第5行。p的定义说明了p是一个函数指针,函数指针虽然也是指针,但他跟普通的指针有一个极大的区别,那就是指针的目标引用符*,对他是无效的!
开篇介绍 大家好,我是Java面试题库的提裤姐,今天这篇是面试系列的第七篇,主要总结了JavaSE中异常类相关面试题,在后续,会沿着第一篇开篇的知识线路一直总结下去,做到日更!...Q: 说一下Java中的异常体系? ? Q: Error和Exception的区别? Error(错误): 系统中的错误,是在程序编译时出现的错误,只能通过修改程序才能修正。...(1)java.lang.NullPointerException 空指针异常;出现原因:调用了未经初始化的对象或者是不存在的对象。...代码在走到第 3 行的时候遇到了一个 MathException,这时第四行的代码就不会执行了,代码直接跳转到 catch语句中,走到第 6 行的时候,异常机制有这么一个原则如果在 catch 中遇到了...return 或者异常等能使该函数终止的话那么有 finally 就必须先执行完 finally 代码块里面的代码然后再返回值。
,而带参数的构造函数则是公有的,根据public和protected的功能,我们要定义一个ostream对象,必须要在参数中传入streambuf类型的指针才可以,否则会报编译错误。...).put(c).put('\n'); return 0; } 这里因为put函数返回的是ostream&类型,所以可以连着使用put函数,代码编译后执行结果如下: [root@mylinux.../a.out c=X [root@mylinux ~]# 4.write函数 ostream的write函数原型如下: //将__s指针所指向的字符串复制出来并插入到缓冲区中,最多插入_...("aaa\n", 4); return 0; } good函数是ostream继承于父类ios的一个成员函数,它用来检查流的状态是否正常,正常则返回true。...按照我的理解,ofstream在往文件中写入数据时,数据实际上是先写到缓冲区中,并没有写到文件中去,所以需要调用一个flush,来确保数据会从缓冲区写到输出设备,也就是文件中去。
0x02 利用方法,第1部分:从任意写入到任意读取 利用该漏洞的主要障碍在于,它虽然提供了写入原语,却没有读取原语或信息泄漏功能。因此,攻击者首先面临的问题是,不知道任何安全或有用的地址。...在我们的漏洞利用代码中,变量gremlin用于索引,因此,gremlin本身被引用为ar1(gremlin)。...在调用对象的方法或属性时,调度机制会封装脚本提供的参数,将它们转换为基于本机堆栈的参数,最后调用实现所需方法或属性的本机函数。因此,调度机制完成了从脚本到本机函数进行调用所需的所有繁重的工作。...我们可以通过颠覆它来调用我们选择的本机代码吗? 事实上,篡改调度的本机目标地址是比较容易的。通常,在调度期间,可以通过在vtable中查找目标函数来定位目标函数。...因此,我们可以随意覆盖内存中COM对象的所有字段。为了让COM对象保持可用状态,只要不破坏调度机制本身正常运行所需的那些字段即可。
2.多线程put后可能导致get死循环 造成死循环的原因是多线程进行put操作时,触发了HashMap的扩容(resize函数),出现链表的两个结点形成闭环,导致死循环。...下图为JDK8中的put操作流程,详情请自行查看源码。 ? 单线程resize过程 ? 首先我们把resize函数中的transfer()的关键代码贴出来: while(null !...3.扩容机制的优化 在JDK7中,对所有链表进行rehash计算;在JDK8中,实际上也是通过取余找到元素所在的数组的位置,取余的方式在putVal里面:i = (n - 1) & hash。...在这n+1位里面,如果第1位是0,那么扩容前后这个key的位置还是在相同的位置(因为hash相同,并且余数的第1位是0,和之前n位的时候一样,所以余数还是一样,位置就一样了);如果这n+1位的第一位是1...这样子就减少了移动所有数据带来的消耗。(慢慢读两遍,想明白了,就觉得这个其实不看图更好理解) ? 常见FAQ HashMap扩容条件 查看JDK7源码的put函数,然后跳转到addEntry函数。
put、get和flip的源代码。...return p;//原始Pos指针返回,用来计算此次取出的数据 } 下面看Bits的put函数: static void putInt(ByteBuffer bb,...读取之前一定要先调用flip()函数,该函数可以控制pos和limit的值,使得缓冲区可以在读写之间很好的切换,它的实现实在Buffer基类中,主要工作就是,limit转换成当前缓冲区在最后一次写入数据后的位置...return this; } 下面看一下get函数,get函数的实现也是在子类HeapByteBuffer中,nextGetIndex函数实在鸡肋Buffer中实现的,主要功能就是get之后的pos...一些函数开头的判断没有详细的去讲,他们的主要工作就是在put和get的时候越界的异常抛出。
正确返回值是文件描述符(其实就是一个小整数,下面会说明由来),错误是-1。 注意:在使用open时,如果不存在该文件,一定要注意第二个参数要传什么参数,第三个参数是必须要传的,不然就是错误文件。...,要用O_RDWR,因为只读和只写的特殊位都是一个位置,只不过是相反,也就是说总会有一个不起作用,下面写起了作用就代表读不会起作用。...缓冲区 首先来看一段代码: 打印正常 重定向正常 这时我加了一个fork创建子进程。 打印正常 这个内容是意料之外的。...这就是为什么刷新缓冲区的函数要传入文件指针,因为里面有缓冲区!...那么:使用重定向之后,写入文件的不是显示器,而是文件,所以就变成全缓存,之前的三天C函数虽然结尾有\n,但是没有写满stdout。
从基类继承来的纯虚函数,在派生类中仍是虚函数。 抽象类中不仅包括纯虚函数,也可包括虚函数。抽象类必须用作派生其他类的基类,而不能用于直接创建对象实例。但仍可使用指向抽象类的指针支持运行时多态性。...这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。...(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用”*指针变量名”的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处...两个不同类型的指针之间可以强制转换(用reinterpret cast)。C#是类型安全的。 16. main 函数执行以前,还会执行什么代码? 答案:全局对象的构造函数会在main 函数之前执行。...为什么? 答案:正确 这个 sizeof是编译时运算符,编译时就确定了 ,可以看成和机器有关的常量。 第25题:引用与指针有什么区别?
在以该类为基类的派生类中,也不能出现这种非虚的同名同返回值同参数个数同参数类型函数。 为什么虚函数必须是类的成员函数: 虚函数诞生的目的就是为了实现多态,在类外定义虚函数毫无实际用处。 ...为什么构造函数不能为虚函数: 因为如果构造函数为虚函数的话,它将在执行期间被构造,而执行期则需要对象已经建立,构造函数所完成的工作就是为了建立合适的对象,因此在没有构建好的对象上不可能执行多态(虚函数的目的就在于实现多态性...注意:当基类的构造函数内部有虚函数时,会出现什么情况呢?结果是在构造函数中,虚函数机制不起作用了,调用虚函数如同调用一般的成员函数一样。当基类的析构函数内部有虚函数时,又如何工作呢?...因此,在析构函数中,虚函数机制也是不起作用的。 C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。...虽然在上面的图中我们可以看到子类的虚表中有Derive自己的虚函数,但我们根本不可能使用基类的指针来调用子类的自有虚函数: Base1 *b1 = new Derive(); b1->f1();
接下来就来看看类是如何定义的。 3. 类的访问限定符 定义一个类,使用时为什么会出现下面的问题呢? 这个是因为C++中有三种访问限定符。...对象中包含类的各个成员 缺陷:每个对象中成员变量是不同的,但是调用同一份函数,如果按照此种方式存储,当一个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间。...C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问...来看看这个代码: 这里i和j是一起放在栈上的。p也是在栈上的。这里p存的指针是在常量区的,这里const。 排除c,static全局的才在静态区,显然this不是。...这里是传一个this空指针,没有解引用,没有问题。 1.下面程序编译运行结果是?
但也存在一些特例,比如:不管choice的值是什么,下面代码finally中的语句就不会被执行。 Q:在类C的一个方法m中调用this.getClass()是不是永远返回C? 不。...Q:我尝试向super传一个方法,但有时候它不正常工作。为什么? 下面是针对上述问题的一段简化后的代码示例: 你需要在调用super的时候非常小心,并且一定要清楚super的方法究竟会做什么。...在一个类中,实例变量的初始化代码可以出现在3个地方: 当你写下new C()时,初始化的顺序是这样的(不考虑内存不够的情况): 1、调用C父类的构造函数(除非C是Object这个类,因为Object没有父类...善用setter方法是件好事,因为在创建对象时需要修改的变量往往之后也可能要修改,所以为什么要在构造函数和setter方法里写一样的代码呢?...不复存在的是程序员失去了对结构体/类分配在堆或栈中的选择权。在Java中,所有对象都被分配到堆中,这就是为什么指针不需要语法标记符(如*)——在Java中,如果它是一个对象的引用,那它就是指针。
1.endl操作符的实现 在标准库头文件中,我找到了endl的操作符重载函数,如下: template inline...那么endl是怎么与<<操作符关联起来的呢,我们在ostream头文件ostream类的声明中又发现了以下代码: __ostream_type& operator<<(__ostream_type...操纵算子分为两类,一类是无参的,定义在ios_base.h头文件中,还有一类是有参的,定义在iomanip头文件中。...const std::tm类型指针,第二个类型是对时间进行格式化的格式字符串 根据第二个参数指定格式输出tm中数据 get_time 第一个参数是const std::tm类型指针,第二个类型是对时间进行格式化的格式字符串...根据第二个参数指定格式把数据填充到tm中 带参数的这些操作函数,前面6个其实是比较好理解的,但是后面四个用起来就比较麻烦了,而且单独使用也是不起作用的,下面我们就后面四个操作符,看一下使用案例,如下
这会让很多人困扰,为什么呢?不要忘记了,其实你最后的代码脚本是EOF,所以,不管你前面自动FTP传送还是获取都是失败的,其实这个正常结束的符号让这个脚本“正常结束”了,因此,$?的返回值就是0了。...get命令下载的文件将保存在本地计算机的工作目录下。该目录是启动FTP时在盘符C:后显示的目录。如果想修改本地计算机的工作目录,可以使用 lcd 命令。...·netrc中应包含的基本命令 FTP中有几十个命令,在.netrc中应该设置的大致有如下几条: 1.default loginpassword 在Internet中,存在大量的匿名ftp...5.hash on ftp中的hash命令,使得在进行文件传输时,每传输1千字节,在屏幕上显示一个”#”号,用户通过观看屏幕上的”#”号,可以很直观地看到传输速度的快慢,以及文件的传输完成情况,以决定进一步的操作...prompt off idle 7200 (空行) 第1行意为缺省情况下,进入anonymous帐户,并以自己的电子邮件地址为口令;第2行至第8行定义了宏init,该宏中的所有
类的两种定义的方式: 一种是将成员函数定义在类里面(编译器可能会当成内联函数处理) 另一种是将成员函数声明与定义分离(工作中推荐第二种) 这里需要注意的是,在类中定义成员函数以及成员变量时,不需要考虑定义的先后顺序...,也就是说,即使成员变量放在成员函数的下面,成员函数中依然可以使用成员变量。...类对象的存储方式 实际上,成员函数虽然是定义在类中,但是它并不存储在类里,假如它是存储在类中,而每个实例化后的对象都各自拥有各自的成员函数,则会造成严重的资源浪费,因为成员函数就好比小区中的健身器材、公共厕所等公共共有的设施...就比如说下面的一个例子: class Date { public: //成员函数(公有的,存储在代码段中) void Init(int year,int month,int day)...= nullptr; //不能仅凭借*以及->来断定就是空指针解引用 //d1->Print1();//程序正常运行 //d1->Print2();//程序崩溃,因为函数内容中涉及到了空指针解引用
局部宏变量是只作用在当前Macro内的,离开了这个Macro这个宏变量就不起作用了~所谓的作用,指的是赋值的值与是否存在该宏变量...一般情况下,如果这个宏变量之前没有在开放式代码(所谓的开放式代码指的是没有被.../*首先:我们在开放式代码中定义一个宏变量*/ %let macvar1=WO SHI YI GE HAO REN; /*放在封闭式代码中:在宏中再一次定义宏变量*/ %macro test; %let...(宏外):&macvar1.; /*执行宏中的宏变量的值*/ %test; /*执行宏后的宏变量的值*/ %put NOTE:第三个解析值(宏外):&macvar1.; 看上面的代码:先猜猜的以此解析的三个宏变量的值是啥...那么还是来看看几行代码 /*首先:我们在开放式代码中定义一个宏变量*/ %let macvar1=WO SHI YI GE HAO REN; %macro test; %put NOTE:第1个解析值(...; %test4; %put NOTE:第2个解析值(宏外):&macvar1.; 全局宏变量实际写宏中作用多么~答案也是显然,非常常用,让宏变量在不同组件的宏中传递...就想下面一个rtf输出宏,用都个组成部分
扩容造成死循环和数据丢失的分析过程 假设现在有两个线程A、B同时对下面这个HashMap进行扩容操作: 正常扩容后的结果是下面这样的: 但是当线程A执行到上面transfer函数的第...为什么说JDK1.8会出现数据覆盖的情况喃,我们来看一下下面这段JDK1.8中的put操作代码: final V putVal(int hash, K key, V value, boolean onlyIfAbsent...hash碰撞,假设两个线程A、B都在进行put操作,并且hash函数计算出的插入下标是相同的,当线程A执行完第六行代码后由于时间片耗尽导致被挂起,而线程B得到时间片后在该下标处插入了元素,完成了正常的插入...除此之前,还有就是代码的第38行处有个++size,我们这样想,还是线程A、B,这两个线程同时进行put操作时,假设当前HashMap的zise大小为10,当线程A执行到第38行代码时,从主内存中获得size...总结 HashMap的线程不安全主要体现在下面两个方面: 1.在JDK1.7中,当并发执行扩容操作时会造成环形链和数据丢失的情况。
但是volatile修饰的成员变量并不具有原子性,在并发下对它的修改是线程不安全的。 下面分别举例来演示这两个特性,并且分析为什么volatile不是线程安全的。...可见性 通过对JMM的学习,我们都知道线程对主内存中共享变量的修改首先会从主内存获取值的拷贝,然后保存到线程的工作内存中。 接着在工作内存中对值进行修改,最终刷回主内存。...通过JMM内存交互协议我们可以知道,一个线程修改共享变量的值需要经过下面这些步骤: 1.线程从主内存中读取(read)共享变量的值,然后载入(load)到线程的工作内存中的变量; 2.使用(use)工作内存变量的值...虽然这时候thread2工作内存中value值的拷贝无效了(因为volatile的特性),但是thread2已经执行完+1操作了,它并不需要再从主内存中获取value的值,所以thread2可以顺利地将...+1后的值赋值给工作内存中的变量,然后刷回主存。
领取专属 10元无门槛券
手把手带您无忧上云