linux下c/c++语法知识点归纳和总结(1)
C++申请动态内存C++继承的优缺点C++的三大特性子类和父类调用构造函数和析构函数的先后顺序什么是引用将引用作为函数参数有哪些特点什么时候需要使用常引用
将引用作为函数返回值类型的好
C++申请动态内存C++继承的优缺点C++的三大特性子类和父类调用构造函数和析构函数的先后顺序什么是引用将引用作为函数参数有哪些特点什么时候需要使用常引用 将引用作为函数返回值类型的好处和需遵循的规则 好处:在内存中不产生被返回值的副本 需遵循的规则: 不能返回局部变量的引用;不能返回函数内部动态分配的变量的引用,因为引用只是作为一个临时变量的出现,并未赋予一个实际的变量,该引用所指向的空间无法被释放;可以返回类成员的引用,但最好是const类型;为了保证连续使用流操作符(>)重载返回值时,操作的是同一个对象,流操作符重载返回值应该声明为引用+-*/这四则运算符不能返回引用引用和多态的关系指针和引用的区别 关联、聚合、组合的区别 主要是在画uml类图时,有关联、聚合和组合的说法。 聚合和组合的区别:就是聚合关系中部分事物和整体事物生存期无关,举个浅显的例子,国和家,国没了,家也就不存在了,这是组合关系,而计算机和它的外设之间,计算机没了,硬件设备还存在,这是聚合关系。 多态(也叫重写和覆盖)的作用什么情况下只能使用类构造函数初始化表而不能赋值c++是否是类型安全的main函数执行以前会执行什么代码描述内存分配方式以及它们的区别struct和class的区别在8086汇编下,逻辑地址和物理地址是怎样转换的请说出const和#define相比,有什么优点简述数组和指针的区别 数组要么在静态存储区创建,要么在栈上创建,指针可以随时指向任意类型的内存: 修改内容上的差别: char a[] = “hello”; a[0] = ‘X’;//正确,编译和运行都不报错 char *p = “hello”;//注意p指向常量字符串 p[0] = ‘X’;//不正确,编译不报错,运行时报错 sizeof计算容量时,数组得出字节数,指针则是4个字节 【文章福利】小编推荐自己的Linux、C/C++技术交流群:【960994558】整理了一些个人觉得比较好的学习书籍、视频资料 共享在里面(包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis ,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker, TCP/IP,协程,DPDK等等.),有需要的可以自行添加哦!~ 节 类成员函数的重载、覆盖和隐藏的区别 重载即为函数重载,重载的特征: (1)相同的范围,也就是在同一个类中 (2)函数名字相同 (3)参数不同 (4)virtual关键字无影响 覆盖是指派生类函数覆盖基类函数,覆盖的特征: (1)不同的范围,即函数分别位于派生类和基类 (2)函数名字相同 (3)参数相同 (4)基类函数必须有virtual关键字 隐藏是指派生类的函数屏蔽了与其同名的基类函数,特征如下: (1)如果派生类的函数与基类的函数同名,但是参数不同,此时不论有没有virtual关键字,基类的函数都将被隐藏 (2)如果派生类的函数与基类的函数同名,参数也相同,但是基类函数没有virtual关键字,此时,基类的函数将被隐藏 总结:函数名相同,参数也相同的情况下,如果基类函数有virtual关键字,则是多态,否则就是隐藏;函数名相同linux语句,参数不同的情况下,如果函数位于同一个类中,则是重载,否则就是隐藏。 main主函数执行完毕后,是否可能会再执行一段代码代码中特殊的注释技术-TODO, FIXME 和 XXX代码中连用两个感叹号友元类的说明多态的内部逻辑 (1)从包含虚函数的类派生一个类时,编译器就为该类创建一个VTABLE,其每一个表项是该类的虚函数地址; (2)在定义该派生类对象时,先调用其基类的构造函数,然后再初始化VPTR,最后再调用派生类的构造函数(从二进制的视野来看,所谓基类子类是一个大结构体,其中this指针开头的四个字节存放虚函数表头指针,执行子类的构造函数的时候,首先调用基类构造函数,this指针作为参数,在基类的构造函数中填入基类的vptr,然后回到子类的构造函数,填入子类的vptr,覆盖基类填入的vptr,如此一来完成vptr的初始化) (3)在实现动态绑定,不能直接采用类对象,而一定要采用指针或者引用,因为采用类对象传值方式,有临时基类对象的产生,而采用指针,则是通过指针来访问外部的派生类对象的vptr来达到访问派生类虚函数的结果。 虚析构函数的作用#ifndef 和 #pragma once的区别__declspec(dllexcept) 和 __declspec(dllimport) #ifdef ASIMOVLIB_EXPORTS #define ASIMOVLIB_API __declspec(dllexport) #else #define ASIMOVLIB_API __declspec(dllimport) #endif __declspec(dllexport): 声明一个导出函数,是说这个函数要从本DLL导出。我要给别人用。一般用于dll中省掉在DEF文件中手工定义导出哪些函数的一个方法。当然,如果你的DLL里全是C++的类的话, 你无法在DEF里指定导出的函数,只能用dllexport导出类。 __declspec(dllimport): 声明一个导入函数,是说这个函数是从别的dll导入,我要用,一般用于使用某个dll的exe中。 不适用__declspec(dllimport)也能正确编译代码,但使用__declspec(dllimport)使编译器可以生成更好的代码。编译器之所以能生成更好的代码,是因为它可以确定函数是否存在于DLL中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨DLL边界的函数调用中。但是,必须使用__declspec(import)才能导入DLL中使用的变量。 explicit关键字的作用 explicit用来防止由构造函数定义的隐式转换,比如:class Base base=10;即Base类只有一个int类型的变量,explicit使用了以后,就不允许这样写。 被声明为explicit的构造函数通常比非explicit的构造函数更受欢迎,因为它们禁止编译器执行非预期的类型转换。除非我有个好理由允许构造函数被用于隐式类型转换,否则我会把它声明为explicit。 printf输出时在%和字母之间插入数字表示场宽的规则?逗号表达式? 例如:printf(“%d %d %d\n”, (a,b,c),b,c); 那么将输出才c,b,c这3个值,因为逗号表达式的值就是表达式中最后一个表达式的值; 即:表达式1,表达式2,表达式3…表达式n 就是表达式n的值。 c语言中标识符第一次字符必须是什么? 第一个字符必须是字母或者下划线,不能是数字。 数据流程图(DFD图)是什么 DFD图是结构化方法的需求分析工具。 hash_set和set的区别? hast_set以hashtable为底层机制,而set以RB-tree(红黑果树)为底层机制; set有元素自动排序功能,而hash_set没有; set可在logN下完成查找、插入和删除等操作,hash_set可在常数时间复杂度下完成这些操作,但是取决于哈希表的负载情况; hast_multiset则允许键值重复; static的用途以及类中使用static的规则。 用途: static限制变量的作用域; static不显示的初始化时,会被隐式的初始化为0; static设置变量的存储域,变量存储在静态区; 类中使用static的规则: 不能通过类名来调用类的非静态成员函数,可以调用静态成员函数; 类的对象可以使用静态成员函数和非静态成员函数; 类的静态成员函数中不能使用类的非静态成员,因为此时静态成员函数已经分配了存储空间,而非静态成员却还没有分配内存,相当于变量声明了但是未定义就直接使用; 类的非静态成员函数(包括常函数)可以使用类的静态成员函数和静态成员变量,并且非静态成员常函数可以修改静态成员变量; 类的静态成员变量必须初始化以后才能使用; 数据库三范式 巴斯-科德范式:第三范式的一个子集,在第一范式基础上,任何非主属性不能对主键子集依赖。 网络编程中设计并发服务器,使用多进程和多线程,请问有什么区别? 1)两者都可以提高程序的并发度,提高程序运行效率和响应时间 2)线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相反。 可以用作switch的参数的类型 int、short、byte、char、long 基本上可以转换为整数的类型都可以用作switch的参数。 linux使用多线程的方法 互斥锁、信号量、条件变量、全局变量、读写锁。 互斥锁:当线程A锁定了互斥变量时,线程B再去锁定时就会被挂起,直到A解锁。 注意:当线程要不断的去轮询检查某个条件以判断是否可以操作需同步的数据时,可使用条件变量提高效率。 信号量:就是一个整数,两个线程对整数进行加减来实现信号量。条件变量:经常和互斥锁一起使用,使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程会解开相应的互斥锁并等待条件发生变化,一旦其他的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此变量阻塞的线程,这些线程将重新锁定互斥锁并重新测试条件是否满足。 pthread_cont_init() pthread_cont_destroy() pthread_cont_wait() //线程解开mutex指向的锁并被条件变量阻塞 pthread_cont_timedwait() //多了时间参数,当时间过了以后,即使条件变量不满足,阻塞也被解除 pthread_cont_signal()/pthread_cont_broadcast //唤醒被条件变量阻塞的线程。 读写锁:可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁。 读写锁适用于对数据读的次数比写的次数多的情况。 API接口: 初始化和销毁: int pthread_rwlock_init(); int pthread rwlock_destroy(); 读加锁、写加锁、解锁: pthread_rwlock_rdlock(); pthread_rwlock_wrlock(); pthread_rwlock_unlock(); 非阻塞获得读锁和写锁: pthread_rwlock_tryrdlock(); pthread_rwlock_trywrlock(); linux系统进程间通信方式为什么要使用linux作为服务器。mysql数据库的引擎 ISAM MYISAM HEAP 什么是红黑数?C程序的内存分配方式select、poll、epoll的区别 select函数 int select(int n,fd_set* readfds, fd_set* writefds, fd_set* errorfds, struct timeval* timeout); 第一个参数n代表最大的文件描述符+1 fd_set是一个集合,存放的是文件描述符 readfds表示我们要监视这些文件描述符里读变化 writefds表示我们要监视它所指向的集合里面的文件描述符的写变化 errorfds表示要监视文件描述符是否发生了错误异常 timeout若为NULL,则select置于阻塞状态,直到监视的某个文件描述符发生变化才返回 timeout若等于0秒0毫秒,则select是一个纯粹的非阻塞函数,不管文件描述符是否变化,立即返回。 timeout大于0时,则在timeout时间内阻塞,timeout时间内若文件描述符有变化则返回,如果超时则立即返回 返回值:负值 select发生错误 正值 有文件描述符发生变化 0 等待超时,没有可读写或者发生错误的文件描述符 poll poll使用pollfd结构 epoll函数与select函数最大的不同在于它不会随着监听fd数目的增长而降低效率,并且select同时监听的fd数目是有限制的,默认最大是1024. int epoll_create(int size);//创建epoll句柄,参数size告诉内核这个监听的数目有多大,但最新版本这个参数已经无用了 int epoll_ctl(); //epoll的事件注册函数,它要先注册需要监听的事件类型 int epoll_wait();//等待事件的发生 select是轮询fd,而epoll是先将文件描述符注册到内核,一旦文件描述符发生变化,内核会采用回调机制,激活这个文件描述符,这样epoll_wait便会知道。 epoll相对于select有点: linux下inode的说明 每个磁盘空间都有一个inode表,inode里面每一个节点存放该空间每个文件的信息,例如:文件的字节数、文件拥有者、所在的组、权限、时间、位置等。 istat 命令查看单个文件; df –i查看磁盘空间inode的使用量。 IP、TCP、UDP数据包大小 注意:这里说的首部是固定长度,但后面还有一些可选字段。 memcache的特性什么是sql注入对称加密算法和非对称加密算法volatile关键字的作用 volatile变量是随时可能发生变化的,它告诉编译器,与volatile变量有关的运算,不要进行任何优化,每次读取volatile变量时都重新从内存读取。 c++中动态联编和静态联编深拷贝和浅拷贝什么是柔性数组? 数组大小待定的数组就是柔性数组。 一般结构体的最后一个元素可以是大小未知的数组。 库函数和系统调用的区别? 库函数调用时面向应用开发的,与系统无关,移植性好。 系统调用是面向底层,偏向硬件,系统内核软中断实现,移植性差。 系统调用是用户程序和内核交互的接口,系统调用的过程如下: 系统调用比库函数调用快。 构造函数里面”初始化列表”和”赋值”的区别 对于内置类型来说,没有区别,对于非内置类型则有区别,如下: 初始化列表只会调用一次构造函数,而赋值会先调用构造,再调用一次赋值函数。 什么情况下只能使用初始化列表: 没有默认构造函数的类; 类中存在const成员或者引用类型的成员(它们只能被初始化); 为什么要字节对齐? 自然对齐:一个变量的内存正好是它长度的整数倍。 需要字节对齐的根本原因在于CPU的效率问题,假设32位机器上int型变量地址是0x00000002,那么CPU取值时需要访问两次内存,一次是0x00000002-0x00000003的short,然后是0x00000004-0x00000005的short,而如果该int型变量的地址是0x00000003,那么CPU则要访问3次内存,即char-short-char,而如果变量是自然对齐的,则CPU访问一次内存就够了。 struct stu { char sex; int length; char name[10]; }; sizeof(struct stu) = 20;//结构体中每个数据类型都要对齐 什么情况下需要手动设置对齐: 设计不同CPU下的通信协议(设计一个结构体,32位和64位都用时)编写硬件驱动程序时寄存器的结构 手动设置对齐方式有两种: 1) #pragma pack(n) #pragma pack() 2) GNU编译时 #define GNUC_PACKED__attribut__((packed)) 浅谈僵尸进程 僵尸进程:当子进程退出时,父进程没有调用wait函数或者waitpid()函数等待子进程结束,又没有显式忽略SIGCHLD信号,那么它将一直保持在僵尸状态,如果这时父进程结束了,init进程会自动接收这个子进程,为它收尸,但如果父进程是一个循环,不会结束,那么子进程就会一直保持僵死状态。 进程状态: 僵尸 休眠 不可中断的休眠 运行 停止式跟踪 Z S D R T 补救办法:杀死僵尸进程的父进程,让init进程来接手,清理掉子进程这个僵尸进程。 僵尸进程的状态:一个进程在调用exit()函数结束时,并没有真正的被销毁,而是留下一个称为僵尸进程的数据结构,僵尸进程放弃了几乎所有的内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保持一个位置,记载该进程的退出状态等信息。 避免僵尸进程的方法: fork函数浅析 pid_t fork(); 返回值:若成功调用一次则返回两个值,子进程返回0,父进程返回子进程的进程id,否则,出错返回-1. 子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。 注意:子进程拥有的是副本,它跟父进程之间是不共享这些存储空间(但是共享代码段)的,因此子进程拥有独立的地址空间。 fork可能出错的原因: 当前进程数量已经达到了系统规定的上限; 系统内存不足; ; for_each的用法? for_each是C++STL中用来遍历容器的函数模板,有3个参数: 第一个是容器开始,例如:map.begin() 第二个是容器结束,例如:map.end(); 第三个是operator(),仿函数,函数对象 当第三个函数有其他参数时,与bind1st和bind2nd一起使用。 例如: void record(const int &n) { cout sysrq-trigger mutable关键字 mutable加在类型前面,表示即使是常量也可以修改 带外数据 OOB数据,也叫带外数据,send/sendto发送数据时以MSG_OOB标记。 带外数据只支持tcp,不支持udp 带外数据发送时不优先,接收时优先; 接收带外数据的系统会发送一个SIGURG信号 自定义类型作为map键时需注意什么?重载 “ (编辑:成都站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |