指针

c++ -- 多态(类)

↘锁芯ラ 提交于 2020-02-07 02:12:58
假期 2020.02 .06 学习资源来源于中国MOOC以及c语言中文网 前言 c++之所以是面向对象的是因为该语言既支持类也支持多态,而多态是什么呢? 定义 多态就是同一个操作作用于不同的对象会产生不同的结果。这个操作一般指的是函数的调用等等。 标准定义 是对于通过基类指针调用基类和派生类中都有的同名、同参数表的虚函数的语句,编译时并不确定要执行的是基类还是派生类的虚函数;而当程序运行到该语句时,如果基类指针指向的是一个基类对象,则基类的虚函数被调用,如果基类指针指向的是一个派生类对象,则派生类的虚函数被调用。这种机制就叫作“多态(polymorphism)”。 虚函数 :在成员函数前加 virtual 即可生成虚函数。注意虚函数只能在类的内部定义成员函数时使用,不能在类外部写成员函数时使用,构造函数与静态成员都不能是虚函数。 多态类 :包含虚函数的类称为“多态类”。 如何构成多态 常判断条件是 有继承关系 继承关系中有同名的虚函数,并且是覆盖关系 存在基类的指针,指向派生类的虚函数,或者引用 那么什么时候声明虚函数呢? 成员函数所在的类是否是基类 成员函数在继承后是否会被新定义或者更改,是的话,需要;否则,不需要。 多态应用 举一个指针类型的例子: 注意:多态的语句调用哪个类的成员函数是在运行时才能确定的,编译时不能确定。多态的函数调用语句被称为是“动态联编”

C++ using新用法、类成员指针

泪湿孤枕 提交于 2020-02-07 01:39:01
一、using新用法 template.h #pragma once #include <iostream> #include <map> template <typename wt> struct map_s { typedef std::map<std::string, wt> type; }; //C++11 template <typename T> using str_map_t = std::map<std::string, T>; int RealFunc(int i, int j) { return i + j; } typedef int(*FuncType)(int, int); using FuncType = int(*)(int, int); typedef unsigned int uint_t; using uint_t = unsigned int; main.cpp #include <iostream> #include "template.h" using namespace std; int main() { map_s<int>::type map1; map1.insert({ "first", 1 }); str_map_t<int> map2; map1.insert({ "second", 1 }); FuncType

c语言 局部变量做返回值 问题

倖福魔咒の 提交于 2020-02-07 01:10:19
一般的来说,函数是可以返回局部变量的。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错。但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错。因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错。准确的来说, 函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的)。 下面以函数返回局部变量的指针举几个典型的例子来说明: 1: [cpp] view plain copy #include <stdio.h> char *returnStr() { char *p= "hello world!" ; return p; } int main() { char *str; str=returnStr(); printf( "%s\n" , str); return 0; } 这个没有任何问题,因为"hello world!"是一个字符串常量,存放在 只读数据段 ,把该字符串常量存放的 只读数据段 的首地址赋值给了指针,所以returnStr函数退出时,该该字符串常量所在内存不会被回收,故能够通过指针顺利无误的访问。 2: [html] view plain copy #include < stdio.h >

函数返回局部变量的几种情况

。_饼干妹妹 提交于 2020-02-07 01:04:33
转载 http://blog.csdn.net/haiwil/article/details/6691854/ 本文主要详细讨论了返回返回局部变量的几种情况,值得大家注意。 一般的来说,函数是可以返回局部变量的。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错。但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错。因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错。准确的来说,函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的)。 下面以函数返回局部变量的指针举几个典型的例子来说明: 1: [cpp] view plain copy #include <stdio.h> char *returnStr() { char *p= "hello world!"; return p; } int main() { char *str; str=returnStr(); printf( "%s\n", str); return 0; } 这个没有任何问题,因为"hello world!"是一个字符串常量,存放在只读数据段,把该字符串常量存放的只读数据段的首地址赋值给了指针,所以returnStr函数退出时

剑指offer速记

核能气质少年 提交于 2020-02-06 23:00:31
一、 const:如果函数参数是指针,且仅作输入用,则必须在类型前面加上const,以用来防止该指针在函数体内被意外修改。 const在*前表示指针所指的内容固定(不允许*abc="789"),指针的指向可变 const int *abc="123" ;abc="345"; const在*后表示指针本身的指向固定(不允许a++),指针所指的内容可变 char tmp[]="123"; int * const abc=tmp;abc[1]='0'; 二、 C++中,四个与类型转换相关的关键字:static_cast、const_cast、reinterpret_cast、dynamic_cast。 空类型的size是1字节,虽然不包含任何信息但是必须在内存中占有一定空间。添加了构造函数和析构函数size不变。如果有虚函数,会为该类型创建虚函数表,并在该类型的每一个实例中添加一个指向虚函数表的指针,32位机器上一个指针4字节,64位机器上一个指针8字节 构造函数不能以本类的对象作为唯一参数,以免和复制构造函数相混淆Complex (Complex c) {...} 来源: https://www.cnblogs.com/dzzy/p/12271201.html

日志统计-双指针

依然范特西╮ 提交于 2020-02-06 20:10:39
小明维护着一个程序员论坛。现在他收集了一份”点赞”日志,日志共有 N 行。 其中每一行的格式是: ts id 表示在 ts 时刻编号 id 的帖子收到一个”赞”。 现在小明想统计有哪些帖子曾经是”热帖”。 如果一个帖子曾在任意一个长度为 D 的时间段内收到不少于 K 个赞,小明就认为这个帖子曾是”热帖”。 具体来说,如果存在某个时刻 T 满足该帖在 [T,T+D) 这段时间内(注意是左闭右开区间)收到不少于 K 个赞,该帖就曾是”热帖”。 给定日志,请你帮助小明统计出所有曾是”热帖”的帖子编号。 输入格式 第一行包含三个整数 N,D,K。 以下 N 行每行一条日志,包含两个整数 ts 和 id。 输出格式 按从小到大的顺序输出热帖 id。 每个 id 占一行。 数据范围 1≤K≤N≤105, 0≤ts,id≤105, 1≤D≤10000 输入样例: 7 10 2 0 1 0 10 10 10 10 1 9 1 100 3 100 3 输出样例: 1 3 做法:指针i为后指针,j为前,维护区间完成模拟。 #include < iostream > #include < cstdio > #include < algorithm > using namespace std ; #define x first #define y second typedef pair < int ,

快慢指针

三世轮回 提交于 2020-02-06 20:00:46
什么是快慢指针 这种模式,有一个非常出门的名字,叫龟兔赛跑。咱们肯定都知道龟兔赛跑啦。但还是再解释一下快慢指针:这种算法的两个指针的在数组上(或是链表上,序列上)的移动速度不一样。还别说,这种方法在解决有环的链表和数组时特别有用。 通过控制指针不同的移动速度(比如在环形链表上),这种算法证明了他们肯定会相遇的。快的一个指针肯定会追上慢的一个(可以想象成跑道上面跑得快的人套圈跑得慢的人)。 咋知道需要用快慢指针模式? 问题需要处理环上的问题,比如环形链表和环形数组 当你需要知道链表的长度或是某个特别位置的信息的时候 那啥时候用快慢指针而不是上面的双指针呢? 有些情形下,咱们不应该用双指针,比如我们在单链表上不能往回移动的时候。一个典型的需要用到快慢指针的模式的是当你需要去判断一个链表是否是回文的时候。 一般情况下,快慢指针出现在链表的频率更高。 快慢指针判断链表有环 快指针fast一次走两步,慢指针slow一次走一步,如果有环的话,它们在环上一定会相遇(值相等),此时就证明有环。所以,如果最终fast == nullptr,那么判断链表无环;如果最终fast == slow,且fast != nullptr,那么链表有环。 快慢指针寻找环入口的原理 第一步:快慢指针从头结点出发。如下图所示。蓝色表示快指针fast,红色表示慢指针slow。 第二步:慢指针slow走到了环入口

链表的C++实现

▼魔方 西西 提交于 2020-02-06 18:17:18
参考用书《数据结构》(秦锋,汤亚玲主编) 贴下代码: # include <iostream> # include <string> using namespace std ; class Node { public : string data ; Node * next ; Node ( ) { next = NULL ; } } ; class Link { public : Node * head ; //头指针 Link ( ) //构造函数 { head = NULL ; } ~ Link ( ) { //析构函数 DeleteAll ( ) ; } void Initiate ( ) ; //初始化 void DeleteAll ( ) ; //删除所有节点 void HeadCreate ( int n ) ; //头插法建表 void TrailCreate ( int n ) ; //尾插法建表 void HeadCreateWithHead ( int n ) ; //建立带表头的链表(从头) void TrailCreateWithTrail ( int n ) ; //建立带表头的链表(从尾) int Length ( ) ; //链表长度 Node * Locatex ( string data ) ; //查找值为x的数据元素 Node *

垃圾回收算法——复制式回收

那年仲夏 提交于 2020-02-06 15:52:00
标记-清扫回收地开销较低,但其可能受到内存碎片问题地困扰。在一个设计良好地系统中,垃圾回收通常只会占用整体执行时间地一小部分,赋值器地执行开销将决定整个程序的性能,因此应当设法降低赋值器的开销,特别是应当尽量提升它的分配速度。标记-整理回收器可以根除碎片问题,而且支持极为快速的“阶跃指针”分配,但它需要多次堆遍历过程,进而显著增加了回收时间。 半区复制算法: 该算法属于追踪式回收算法。回收器在复制过程中会进行堆整理,从而可以提升赋值器的分配速度,且回收过程只需对存活对象遍历一次。其最大的缺点在于堆的可用空间降低了一半。 1.半区复制回收 基本的复制式回收器会将堆划分为两个大小相等的半区,分别是来源空间和目标空间。当堆空间足够时,在目标空间中分配新对象的方法是根据对象大小简单地增加空闲指针,如果可用空间不足,则进行垃圾回收。回收器在将存活对象从来源空间复制到目标空间之前,必须先将两个半区的角色互换。在回收过程中,回收器简单地将存活对象从来源空间中迁出;在回收完成后,所有存活对象将紧密排布在目标空间地一端。在下一轮回收之前,回收器将简单地丢弃来源空间(以及其中的对象),但在实际应用中基于安全考虑,许多回收器在初始化下轮回收过程之前都会先将该区域清零。 与标记-整理回收不同,半区复制回收无须在对象头部引入额外空间。由于来源空间中的对象在复制完成后便不再使用

C++指针探讨 (四) 函数对象

Deadly 提交于 2020-02-06 11:41:38
函数对象不是函数指针。但是,在程序代码中,它的调用方式与函数指针一样,后面加个括号就可以了。   这是入门级的随笔,说的是函数对象的定义,使用,以及与函数指针,成员函数指针的关系。 沐枫小筑 函数对象实质上是一个实现了operator()--括号操作符--的类。 例如: class Add { public: int operator ()( int a, int b) { return a + b; } }; Add add; // 定义函数对象 cout << add( 3 , 2 ); // 5 函数指针版本就是: int AddFunc( int a, int b) { return a + b; } typedef int ( * Add) ( int a, int b); Add add = & AddFunc; cout << add( 3 , 2 ); // 5 呵呵,除了定义方式不一样,使用方式可是一样的。都是: cout << add( 3 , 2 ); 既然函数对象与函数指针在使用方式上没什么区别,那为什么要用函数对象呢?很简单,函数对象可以携带附加数据,而指针就不行了。 下面就举个使用附加数据的例子: class less { public : less( int num):n(num){} bool operator ()( int value) {