指针

内存管理:野指针以及非法内存操作

*爱你&永不变心* 提交于 2020-02-21 22:55:19
如果一个指针指向的内存没有访问权限,或者指向一块已经释放的内存,那么就无法对该指针进行操作,这样的指针称为野指针。 规避野指针 指针变量如果暂时不需要赋值,以定要初始化为nullptr,因为任何指针变量被创建时不会自动成为nullptr,它的缺省值是随机的。 当指针指向的内存被释放时,要将指针的值设置为nullptr,因为free()只是释放掉了内存,并未改变指针的值。 来源: https://www.cnblogs.com/xiaobaizzz/p/12343485.html

栈与队列

旧巷老猫 提交于 2020-02-21 19:37:30
目录 1 栈的定义 2 栈的顺序存储结构及实现 2.1 栈的顺序存储结构 2.2 栈的顺序存储结构--进栈出栈操作 3 两栈共享空间 4 栈的链式存储结构及实现 4.1 栈的链式存储结构--进栈操作 4.2 栈的链式存储结构--出栈操作 5 栈的应用--四则运算表达式求值 5.1 后缀表达式计算结果 5.2 中缀表达式转后缀表达式 6 队列的定义 7 循环队列 7.1 队列顺序存储 7.2 循环队列定义 8 队列的链式存储结构及实现 8.1 队列的链式存储结构--入队操作 8.2 队列的链式存储结构--出队操作 1 栈的定义 栈是限定仅在表尾进行插入和删除操作的线性表。允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈,栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构。 栈是一个线性表,栈元素具有线性关系,即前驱后继关系,栈的表尾是指栈顶,而不是栈底。栈底是固定的,最先进栈的只能在栈底,栈的插入操作,叫作进栈,栈的删除操作,叫作出栈。 2 栈的顺序存储结构及实现 2.1 栈的顺序存储结构 栈的顺序存储其实也是线性表存储的简化,称为顺序栈;线性表是用数组来实现的,下标为0的一端作为栈底比较好,因为首元素都存在栈底,变化最小,所以让它作栈底。 定义一个top变量指示栈顶元素在数组中的位置,若存储栈的长度为StackSize

字符串模式匹配KMP算法

拥有回忆 提交于 2020-02-21 17:02:10
字符串模式匹配指的是,找出特定的模式串在一个较长的字符串中出现的位置。 朴素的模式匹配算法 很直观的可以写出下面的代码,来找出模式串在一个长字符串中出现的位置。 1: /* 2: 朴素的模式匹配算法 3: 功能:字符串的模式匹配 4: 参数: 5: s:目标串 6: p:模式串 7: pos:开发匹配的位置 8: 返回值: 9: 匹配成功,返回模式串在目标串的其实位置 10: 匹配不成功,返回-1 11: */ 12: int match(const char * s ,const char * p,int pos){ 13: int i = pos ; 14: int j= 0 ; 15: while(s[i] != '\0' && p[j] != '\0') { 16: if(s[i] == p[j]) { 17: i ++ ; 18: j ++ ; 19: }else { 20: i = i - j + 1; 21: j = 0 ; 22: } 23: } 24: 25: if(p[j] == '\0') 26: return i - j ; 27: else 28: return -1 ; 29: } 上面的代码,s就是目标串,p是模式串,pos指定从s的什么位置开始匹配p。其实现思想也很简单: 当s[i] == p[j]时,目标串和模式串的指针都向后移动一位,进行匹配

快慢指针

有些话、适合烂在心里 提交于 2020-02-21 15:48:36
快慢指针中的快慢指的是移动的步长,即每次向前移动速度的快慢。例如可以让快指针每次沿链表向前移动2,慢指针每次向前移动1次。 快慢指针的应用 判断单链表是否为循环链表 让快慢指针从链表头开始遍历,快指针向前移动两个位置,慢指针向前移动一个位置;如果快指针到达NULL,说明链表以NULL为结尾,不是循环链表。如果 快指针追上慢指针,则表示出现了循环。 fast=slow=head; while(true){ if (fast==NULL || fast->next==NULL) return false; else if (fast==slow || fast->next==slow) return true; else{ fast=fast->next->next; slow=slow->next; } 在有序链表中寻找中位数 该方法在不借助计数器变量实现寻找中位数的功能。原理是:快指针的移动速度是慢指针移动速度的2倍,因此当快指针到达链表尾时,慢指针到达中点。程序还要考虑链表结点个数的奇偶数因素,当快指针移动x次后到达表尾(1+2x),说明链表有奇数个结点,直接返回慢指针指向的数据即可。如果快指针是倒数第二个结点,说明链表结点个数是偶数,这时可以根据“规则”返回上中位数或下中位数或(上中位数+下中位数)的一半。 while (fast&&slow) { if (fast->next

[置顶] Effective STL 学习笔记

久未见 提交于 2020-02-21 11:39:33
看Effective STL 作的一些笔记,希望对各位有帮助。 以下是50条条款及相关解释。 容器 1. 慎重选择容器类型,根据需要选择高效的容器类型。 2. 不要试图编写独立于容器类型的代码。 3. 确定容器中的对象拷贝正确而高效。也就是防止在存在继承关系时发生剥离。 4. 调用empty而不是检查size()是否为0来判断容器是否为空。 原因是调用empty比检查size()更加高效。 5. 尽量使用区间成员,而不是多次使用与之对应的单元素成员函数,原因是这样更加高效。 如尽量使用vector的 assign 或 insert 成员函数,而不是一直使用 push_back 。 6. 小心C++编译器最烦人的分析机制 。如 下面的代码中的第二句被C++解释成为了函数声明,这很奇怪但又符合标准。 ifstream dataFile ("ints.dat") list <int> data( istream_iterator<int>(dataFile), istream_iterator<int>() ); // 被解释成为函数声明 正确的写法是这样的,注意第一参数两边的括号: list <int> data( ( istream_iterator<int>(dataFile) ) , istream_iterator<int>() ); 这是因为C+

C++里的四种强制类型转换

时光毁灭记忆、已成空白 提交于 2020-02-21 07:12:51
C语言里将类型符号作为强制类型转换运算符的做法在C++中得到了兼容,但是C++中引入了四种功能不同的强制类型转换运算符:static_cast、reinterpret_cast、const_cast、dynamic_cast 1.为什么要新增四种强制类型转换? 强制类型转换具有一定风险,如:把整型转换为指针类型、将基类指针转换为派生类指针、将一种函数指针转换为另一种函数指针,将常量指针转换为非常量指针等。C++新引用四种强制类型转换主要是为了规避这种风险: a. 将int转换为double是没有风险的,而将常量指针转换为非常量指针,将int转换为指针类型都是高风险的,C中并未对这两种情况作区分 b. 将多态的基类指针转换为派生类指针时并不检查安全性,无法判断转换后的指针是否指向一个派生类对象 c. 如果强制类型转换出错,很难排查出错误 2.C++中强制类型转换运算符的用法 强制类型转换运算符<要转换的类型>(待转换的表达式) 如:double num = static_cast (1+2); // 将1+2转换为浮点类型 3.static_cast static_cast主要用于“低风险”的类型转换,如 整数、浮点数和字符类型 的转换,如果对象 重载了强制类型转换运算符 T(T是int、char或其他类型),则static_cast也可以用于将对象转换为T类型;而像整型和指针这种

C++ 常见面试题目

送分小仙女□ 提交于 2020-02-21 07:05:14
const作用 (1)可以定义const常量,具有不可变性。 (2)便于进行类型检查。(而宏不会进行类型检查)。 (3)可以保护被修饰的东西,防止意外的修改。 (4) 可以节省空间。 static作用 1.隐藏:一个文件中的全局变量在另外一个文件中使用extern声明就能使用,声明了static就不能了 一个函数内的static变量具有全局生命期,但只在这个函数中可见 2.记忆功能和全局生存期 3.默认初始化为0 4.类的静态成员函数是属于整个类而非类的对象,所以它没有this指针 5.不能将静态成员函数定义为虚函数。 6.不可以同时用const和static修饰成员函数。 什么函数不能声明为虚函数 1:只有类的成员函数才能说明为虚函数; 2:静态成员函数不能是虚函数; 3:内联函数不能为虚函数; 4:构造函数不能是虚函数; 5:析构函数可以是虚函数,而且通常声明为虚函数。 指针和引用的区别 本质上:指针是一个新的变量,只是这个变量存储的是另一个变量的地址,我们通过访问这个地址来修改变量。 而引用只是一个别名,还是变量本身。对引用进行的任何操作就是对变量本身进行操作,因此以达到修改变量的目的。 1.引用必须被初始化,指针不必 2.引用初始化以后不能被改变,指针可以改变所指的对象。 3.不存在指向空值的引用,但是存在指向空值的指针。 4."sizeof引用"得到的是所指向的变量(对象

C++学习随笔之十一:C++中的代码重用

帅比萌擦擦* 提交于 2020-02-21 05:43:58
引言: C++ 的一个主要目的是代码重用,提高效率,公有继承是实现这个目的的一种机制。还有其他的机制,本部分主要介绍其他代码重用方法,一种是包含、组合或层次化,另一种是私有或保护继承,通常组合、私有继承和保护继承哟国语实现 has-a 关系,即新的对类将包含另一个类的对象。还有一种就是和函数模板对应的类模板。 1. 包含对象成员的类: 包含对象的类就是这样一种类:类中包含了这样的一个类成员:本身是另一个类的对象。这种方法称为包含、组合或层次化。 C++和约束:C++包含让程序员能够限制程序结构的特性——使用explicit防止单参数构造函数的隐式转换,使用const限制方法修改数据等等。这样做的根本原因是:在编译阶段出现错误要比在运行阶段出现错误要好,要优。 初始化顺序:当初始化列表包含多个项目时,这些项目被初始化的顺序为它们被声明的顺序,而不是它们在初始化列表中的顺序。例如: Student(const char *str,const double *pd,int n):scores(pd,n),name(str){} 则name成员仍将首先初始化,因为在类定义中它首先被声明。 接口和实现:使用公有继承是,类可以继承接口,可能还有实现(基类的纯虚函数提供接口,但不提供实现)。获得接口是is-a关系的组成部分。而是用组合,类可以获得实现,但不能获得接口。不继承接口是has

leetcode题解--#202.快乐数

落花浮王杯 提交于 2020-02-20 18:16:17
题目链接 题目描述:编写一个算法来判断一个数是不是“快乐数”。 一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。 实例: 输入: 19 输出: true 解释: 12 + 92 = 82 82 + 22 = 68 62 + 82 = 100 12 + 02 + 02 = 1 题解:   常规方法当然是通过哈希表判重,即通过set(c++)记录每次计算得到的数来判断是否跳出循环。本文将介绍另一种方法,也就是利用Floyd Cycle思想来判断是否是1跳出循环。通俗来讲,就是快慢指针。   题目给出了快乐数的定义, 注意 :是快乐数最终会变成1;若不是则可能掉入死循环。意味着我们要思考如何跳出循环。这时,利用快慢指针可破循环。为什么这么说?顾名思义,可以假设快慢指针在同一起点(也就是出入值n)出发,快指针一次计算两步,慢指针一次计算一步,那么,在某一时刻,无论它是不是快乐数,快慢指针都会相遇。也就意味着循环周期结束。这时,我们可以跳出循环,判断是否是1导致跳出循环。   注:这里快慢指针分别走几步没有限制,掌握思想即可。当然,快两步慢一步效率相对高一些。 算法 class Solution { public : bool isHappy (

this指针

允我心安 提交于 2020-02-20 17:34:40
this指针 javascript中this指针是动态的,主要是根据当前函数执行上下文及函数调用方式决定的. 以函数方法调用时 this 指针全局或严格模式中为 undefined 以方法调用时 this 是指针当前对象实例的. 以构造函数方式时 this 指向当前创建的实现对象 apply 、 call 、 lambda表达式 可用于绑定this指针. 注意:别绕晕了 函数方式调用 // 以函数方式调用 var x = 2 function test() { console.log(this.x); // 输出 2 } test() // this 为全局对象 windown 以方法调用 // 以方法调用 var x = "x"; let o = { x: 2 }; console.log(o.x); // this指针o实例 构造函数方式 var x = 1; function Test() { this.x = "5x"; } let b = new Test(); console.log(b.x); // this指针b实例对象 apply与call绑定this apply与call接收的函数参数不同,使用方法都是一样的. // apply var b = "b" function test() { console.log(this.b) } let o = { b:22