c/c++知识点总结(一)

最近小伙伴在问,怎么还不更新,再不更新秋招都要结束了,于是我放下手上的活,来写一些总结吧,今天发下关键字的总结吧

一、关键字

1. Const

① 定义只读常量
② 修饰函数参数表示在函数体内不希望改变参数的值
③ 修饰函数返回值表示返回值不可变,多用于返回指针
const int p; //p是一个常整数型
int const p; //p是一个常整数型

const int* p; //p可变,p指向的内容不可变
int* const p; //p不可变,p指向的内容可变
int const* p; //p可变,p指向的内容不可变
const int* const p; // p和p指向的内容都不可变

2. Static

(1) static修饰的内置类型变量分为静态全局变量和静态局部变量,静态变量内存分配在 .data段,生成的符号为local类型的符号,在链接阶段进行符号解析时不做处理。静态变量只初始化一次,未初始化的静态变量会默认初始化为0。静态全局变量只在本文件可见,外部文件无法访问。而静态局部变量只在定义的作用域内可见,但他们的生存周期都是整个程序运行时期。
(2) static修饰的成员方法为静态成员方法,静态成员方法可以在类内或类外定义,但必须在类内声明;static成员方法没有this指针,所以不能直接引用非static数据成员或调用类的非static成员方法,只能调用类的static成员数据和static成员方法;static成员不是任何对象的组成,不依赖对象的调用所以static成员方法不能被声明为const,因为const只限定该类的对象;static成员方法不能同时被声明为虚函数。

3. volatile(这个很重要,做嵌入式朋友常用的)

优化器在用到使用该关键字定义的变量时需要小心地去内存中取值,而不是取寄存器的备份。
例子:
   ① 并行设备的硬件寄存器
   ② 一个中断服务子程序会访问到的非自动变量
   ③ 多线程应用中被几个任务共享的变量

4. mutable

mutable 是为了突破 const 的限制而设置的。可以用来修饰一个类的成员变量。被 mutable 修饰的变量,将永远处于可变的状态,即使是 const 函数中也可以改变这个变量的值。

5. auto

(1) C++中的auto关键字是一个类型说明符,通过变量的初始值或者表达式中参与运算的数据类型来推断变量的类型。
(2) 在C语言中使用auto定义的变量可以不予初始化,但在C++中必须初始化

6. extern

extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。另外,extern也可用来进行链接指定。

7. struct与union区别

最大的区别在于内存利用。
(1)struct各成员各自拥有自己的内存,各自使用互不干涉,同时存在的,遵循内存对齐原则。一个struct变量的总长度等于所有成员的长度之和。
(2)union 各成员共用一块内存空间,并且同时只有一个成员可以得到这块内存的使用权(对该内存的读写),各变量共用一个内存首地址。因而,联合体比结构体更节约内存。一个union变量的总长度至少能容纳最大的成员变量,而且要满足是所有成员变量类型大小的整数倍。不允许对联合体变量名U2直接赋值或其他操作。

8. struct 与class

C++中struct与class关键字一般可以通用,只有一个很小的差别。struct成员默认属性是public,而class成员为private。

9. #define与typedef区别

define是预处理指令,在编译时不进行任何检查,只进行简单的替换
typedef是在C语言中用来为复杂的声明定义简单的别名,它本身是一种存储类的关键字,与auto、extern、mutable、static、register等关键字不能出现在同一个表达式中。

10. override 与 final

(1) override的作用就出来了,它指定了子类的这个虚函数是重写的父类的
(2) 放在类名后面禁止继承 class Teacher final{};
(3) 放在函数后,禁止重写 void teachMethod() final

二、语法现象

1.重入函数与不可重入函数

不可重入函数:在实时系统的设计中,经常会出现多个任务调用同一个函数的情况。如果有一个函数不幸被设计成为这样:那么不同任务调用这个函数时可能修改其他任务调用这个函数的数据,从而导致不可预料的后果。(使用系统资源:比如全局变量区,中断向量表等)
1)函数体内使用了静态的数据结构;
2)函数体内调用了malloc() 或者 free() 函数;
3)函数体内调用了标准 I/O 函数

重入函数:指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。

① 编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作上锁解锁操作)等手段对其加以保护。
② 在写函数时候尽量使用局部变量(例如寄存器、堆栈中的变量);

2.回调函数

#include<stdio.h>
#include<stdlib.h>
void basketball()//函数1
{
printf(“选择篮球\n”);
}
void football()//函数2
{
printf(“选择足球\n”);
}
void selectball(void(*ball)(),char color[],double size)//函数3
{
printf(“选择什么球?:\n”);
printf("%s%1.2f\n",color,size);
ball();
}
int main(void)
{
char color[] = “red”;
selectball(basketball, color,0.1234);
selectball(football, color,0.1235);
system(“pause”);
return 0;
}

3.内存四区

在这里插入图片描述

数据区:静态(全局区)和常量区 .bss(未初始化数据).data(数据)\rodata(只读数据)
堆区:手动释放.heap
栈区:自动释放.stack
代码区:存放二进制代码.text
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
int a = 5;//数据区(全局)
int main(void)
{
int b = 2;//b栈区 2放在数据区
int *c=&b;//c栈区
int *d = (int *)malloc(10 * sizeof(int));//d在栈区,堆区开辟空间,将堆区地址赋给d
static int e =6;//数据区(静态区)
printf("%x,%x,%x,%x,%x", &a, &b, &c, &d, &e);
system(“pause”);
return 0;

}

4.大端小端

1).大端存储:大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中
2).小端存储:小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中
eg:0x12345678
在这里插入图片描述

5.多态

(1)动态多态通过虚函数来实现
(2)静态多态没有虚函数根对象类型有关

6.构造与析构

(1)构造:对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数->由构造函数完成成员的初始化工作 构造函数访问从父到子
(2)析构:
 调用类的析构函数
 销毁类的数据成员,与创建顺序相反
 如果有父类,调用父类的析构函数
 注:所有的析构函数最好使用virtual。如果前面的析构函数没有声明为virtual,代码也可以继续运行。然而,如果代码使用delete删除一个实际指向派生类的基类指针,析构函数调用链将被破坏

7.虚函数

(1)虚函数 :
 virtual returntype func(parameter
 虚函数的引入实现动态联编
 虚表存放虚函数地址,当调用指针时,虚表与指针对象指针绑定
 虚函数只能在基类中定义
 析构函数使用虚函数,可以实现动态析构,防止内存泄漏
 注:在有虚函数的类中,类的最开始部分是一个虚函数表的指针,这个指针指向一个虚函数表,表中放了虚函数的地址,实际的虚函数在代码段(.text)中。当子类继承了父类的时候也会继承其虚函数表,当子类重写父类中虚函数时候,会将其继承到的虚函数表中的地址替换为重新写的函数地址。使用了虚函数,会增加访问内存开销,降低效率

(2)纯虚函数
纯虚函数 virtual returntype func(parameter)=0

8.重载、重写、隐藏

(1)重载:在同一个作用域下,函数名相同,函数的参数不同(参数不同指参数的类型或参数的个数不相同)
(2)重写:在不同的作用域下(一个在父类,一个在子类),函数的函数名、参数、返回值完全相同,父类必须含有virtual关键字(协变除外)
(3)隐藏(重定义):在不同的作用域下(这里不同的作用域指一个在子类,一个在父类 ),函数名相同的两个函数构成重定义。调用时必须指定作用域,如果不使用就会使用当前对象中函数。注意:当父类和子类的成员变量名相同时,也会构成隐藏。

9.浅拷贝与深拷贝

(1)浅拷贝:假设B复制了A,修改A的时候,看B是否发生变化:如果B跟着也变了,说明是浅拷贝,拿人手短!(修改堆内存中的同一个值,指向空间相同)
(2)深拷贝:如果B没有改变,说明是深拷贝,自食其力!(修改堆内存中的不同的值,指向不同内存空间,空间小一致)
注:在对含有指针成员的对象进行拷贝时,必须要自己定义拷贝构造函数,使拷贝后的对象指针成员有自己的内存空间,即进行深拷贝,这样就避免了内存泄漏发生。

10.智能指针

智能指针出现的原因:智能指针的作用是管理一个指针,因为存在以下这种情况:申请的空间在函数结束时忘记释放,造成内存泄漏。使用智能指针可以很大程度上的避免这个问题,因为智能指针就是一个类,当超出了类的作用域时,类会自动调用析构函数,析构函数会自动释放资源。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间。

待续…

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页