系统自带的头文件用尖括号括起来,表示编译器先在用户的工作目录下搜索头文件,如果搜索不到则到系统默认目录下去寻找,所以双引号一般用于包含用户自己编写的头文件。如:#include “student.h” , #include “XXXX.h” 。
用户自定义的文件用双引号括起来,编译器首先会在用户目录下查找,然后在到C++安装目录(比如VC中可以指定和修改库文件查找路径,Unix和Linux中可以通过环境变量来设定)中查找。所以一般尖括号用于包含标准库文件,如:#include
https://blog.csdn.net/ruyue_ruyue/article/details/8211809
https://blog.csdn.net/weixin_34179762/article/details/88729259
计算机网络——五层与七层模型
https://www.cnblogs.com/qishui/p/5428938.html
https://www.jianshu.com/p/e136ec79235c
红黑树是一种含有红黑结点并能自平衡的二叉查找树。它必须满足下面性质:
性质1:每个节点要么是黑色,要么是红色。
性质2:根节点是黑色。
性质3:每个叶子节点(NIL)是黑色。
性质4:每个红色结点的两个子结点一定都是黑色。
性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。
https://zhuanlan.zhihu.com/p/83567235
提供迭代器访问元素,但是无法使用迭代器改变元素值,因为 key就是 value,set的元素必须独一无二,因此 insert 用的是 rb_tree 的 insert_unique() 函数。multiset 元素的 key 可以重复。因此 insert 用的是 rb_tree 的insert_equal() 函数。
客户端获取URL - > DNS解析 - > TCP连接 - >发送HTTP请求 - >服务器处理请求 - >返回报文 - >浏览器解析渲染页面 - > TCP断开连接
访问一个URL经历了哪些过程
两者最大的不同就是 TCP 提供可靠的传输,而 UDP 提供的是不可靠传输
UDP能够进行广播
https://blog.csdn.net/zhang6223284/article/details/81414149
TCP 和 UDP 的区别
TCP 的顺序问题,丢包问题,流量控制都是通过滑动窗口来解决的,拥塞控制时通过拥塞窗口来解决的
什么是面向连接,什么是面向无连接
在互通之前,面向连接的协议会先建立连接,如 TCP 有三次握手,而 UDP 不会
TCP 为什么是可靠连接
https://my.oschina.net/u/4269462/blog/3195211
https://www.cnblogs.com/findumars/p/7486665.html
github的文章 和这个题目无关的
https://blog.csdn.net/chrise_/article/details/80449028
https://blog.csdn.net/qq_38950316/article/details/81087809
滑动窗口协议
解决可重复读的方法
有两个策略可以防止这个问题的发生:
(1) 推迟事务2的执行,直至事务1提交或者回退。这种策略在使用锁时应用。
(2) 而在多版本并行控制中,事务2可以被先提交。而事务1,继续执行在旧版本的数据上。当事务1终于尝试提交时,数据库会检验它的结果是否和事务1、事务2顺序执行时一样。如果是,则事务1提交成功。如果不是,事务1会被回退。
参考链接:https://www.cnblogs.com/balfish/p/8298296.html
数据库中的事务,事务的隔离级别
https://www.cnblogs.com/sueyyyy/p/12012570.html
https://blog.csdn.net/xiaoming100001/article/details/81109617
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
https://blog.csdn.net/zou_albert/article/details/107914264
在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
SELECT DISTINCT A.name FROM Student A
WHERE A.name not in(
SELECT Distinct S.name FROM Student S WHERE S.score <80)
MySQL (8) 聚集索引 非聚集索引 聚簇索引 稀疏索引 稠密索引
vector和数组类似,拥有一段连续的内存空间,并且起始地址不变。
因此能高效的进行随机存取,时间复杂度为o(1);
但因为内存空间是连续的,所以在进行插入和删除操作时,会造成内存块的拷贝,时间复杂度为o(n)。
另外,当数组中内存空间不够时,会重新申请一块内存空间并进行内存拷贝。
list是由双向链表实现的,因此内存空间是不连续的。
只能通过指针访问数据,所以list的随机存取非常没有效率,时间复杂度为o(n);
但由于链表的特点,能高效地进行插入和删除。
与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list 的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置。
deque是一个double-ended queue,它的具体实现不太清楚,但知道它具有以下两个特点:
它支持[]操作符,也就是支持随即存取,并且和vector的效率相差无几,它支持在两端的操作:push_back,push_front,pop_back,pop_front等,并且在两端操作上与list的效率也差不多。
平台原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。————- 比如,有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐。
性能原因:内存对齐可以提高存取效率。————- 比如,有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。
https://songlee24.github.io/2014/09/20/memory-alignment/
struct Q{
char c;
int num1;
double num2;
};
struct
{
int i; // 4个字节
char c1; // 1个字节
char c2; // 1个字节
}x1;
struct
{
char c1; // 1个字节
int i; // 4个字节
char c2; // 1个字节
}x2;
struct
{
char c1; // 1个字节
char c2; // 1个字节
int i; // 4个字节
}x3;
int main()
{
printf("%d\n",sizeof(x1)); // 输出8
printf("%d\n",sizeof(x2)); // 输出12
printf("%d\n",sizeof(x3)); // 输出8
return 0;
}
问上述代码中sizeof(Q)为多少? 16 实际上这是考察struct结构地址对齐的问题
struct的对其系数和以下几个关系有关
https://www.cnblogs.com/zhao-zongsheng/p/9099603.html
对齐规则
https://blog.csdn.net/liitdar/article/details/80337871
最典型的例子就是std命名空间,C++标准库中所有标识符都包含在该命名空间中
https://blog.csdn.net/lx_392754/article/details/52220676
1、内存溢出
内存溢出是指程序在申请内存时没有足够的内存空间供其使用。原因可能如下:
(1)内存中加载的数据过于庞大;
(2)代码中存在死循环;
(3)递归调用太深,导致堆栈溢出等;
(4)内存泄漏最终导致内存溢出;
2、内存泄漏
内存泄漏是指使用new申请内存, 但是使用完后没有使用delete释放内存,导致占用了有效内存。
https://www.cnblogs.com/outs/p/8964941.html
https://blog.csdn.net/invisible_sky/article/details/78205461
添加链接描述C++面试常见题目4_内存管理,内存泄露
内存泄漏的几种情况
根据子网掩码计算最大主机数,广播地址
计算机网络——子网划分(内含习题讲解)
常用的操作系统进程(作业)调度算法
const 与 #define 区别
#define N 2+3 //我们预想的N值是5,我们这样使用N
double a = N/2; //我们预想的a的值是2.5,可实际上a的值是3.5
#define PI 3.14 //预处理后 占用代码段空间
const float PI=3.14; //本质上还是一个 float,占用数据段空间
空初大小多变const
C++中四种类型转换是:static_cast, dynamic_cast, const_cast, reinterpret_cast
1、const_cast
用于将const变量转为非const
2、static_cast
用于各种隐式转换,比如非const转const,void*转指针等, static_cast能用于多态向上转化,如果向下转能成功但是不安全,结果未知;
3、dynamic_cast
用于动态类型转换。只能用于含有虚函数的类,用于类层次间的向上和向下转化。只能转指针或引用。向下转化时,如果是非法的对于指针返回NULL,对于引用抛异常。要深入了解内部转换的原理。
向上转换:指的是子类向基类的转换
向下转换:指的是基类向子类的转换
它通过判断在执行到该语句的时候变量的运行时类型和要转换的类型是否相同来判断是否能够进行向下转换。
4、reinterpret_cast
几乎什么都可以转,比如将int转指针,可能会出问题,尽量少用;
5、为什么不使用C的强制转换?
C的强制转换表面上看起来功能强大什么都能转,但是转化不够明确,不能进行错误检查,容易出错。
https://www.jianshu.com/p/1a2310f1b58e
STL的优点:
1.实现数据结构和算法的分离,使得STL非常通用。
2.STL具有高可重用性,高性能,高移植性,夸平台的优点。
高可重用性:STL中几乎所有的代码都采用了模板类和模板函数的方式实现,代码重用性高。
高性能:如map,采用红黑数的变体实现,效率高。
高移植性:STL模块很容易移植。
C++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c++11支持,并且第一个已经被11弃用。
为什么要使用智能指针:
智能指针的作用是管理一个指针,因为存在以下这种情况:申请的空间在函数结束时忘记释放,造成内存泄漏。使用智能指针可以很大程度上的避免这个问题,因为智能指针就是一个类,当超出了类的作用域是,类会自动调用析构函数,析构函数会自动释放资源。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间。
采用所有权模式。
auto_ptr< string> p1 (new string ("I reigned lonely as a cloud.”));
auto_ptr p2;
p2 = p1; //auto_ptr不会报错.
此时不会报错,p2剥夺了p1的所有权,但是当程序运行时访问p1将会报错。所以auto_ptr的缺点是:存在潜在的内存崩溃问题!
unique_ptr实现独占式拥有或严格拥有概念,保证同一时间内只有一个智能指针可以指向该对象。它对于避免资源泄露(例如“以new创建对象后因为发生异常而忘记调用delete”)特别有用。
采用所有权模式,还是上面那个例子
复制代码
1
2
3
unique_ptr p3 (new string (“auto”)); //#4
unique_ptr p4; //#5
p4 = p3;//此时会报错!!
编译器认为p4=p3非法,避免了p3不再指向有效数据的问题。因此,unique_ptr比auto_ptr更安全。
另外unique_ptr还有更聪明的地方:当程序试图将一个 unique_ptr 赋值给另一个时,如果源 unique_ptr 是个临时右值,编译器允许这么做;如果源 unique_ptr 将存在一段时间,编译器将禁止这么做,比如:
unique_ptr pu1(new string (“hello world”));
unique_ptr pu2;
pu2 = pu1; // #1 not allowed
unique_ptr pu3;
pu3 = unique_ptr(new string (“You”)); // #2 allowed
其中#1留下悬挂的unique_ptr(pu1),这可能导致危害。而#2不会留下悬挂的unique_ptr,因为它调用 unique_ptr 的构造函数,该构造函数创建的临时对象在其所有权让给 pu3 后就会被销毁。这种随情况而已的行为表明,unique_ptr 优于允许两种赋值的auto_ptr 。
注:如果确实想执行类似与#1的操作,要安全的重用这种指针,可给它赋新值。C++有一个标准库函数std::move(),让你能够将一个unique_ptr赋给另一个。例如:
unique_ptr ps1, ps2;
ps1 = demo(“hello”);
ps2 = move(ps1);
ps1 = demo(“alexia”);
cout << *ps2 << *ps1 << endl;
shared_ptr实现共享式拥有概念。多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用被销毁”时候释放。从名字share就可以看出了资源可以被多个指针共享,它使用计数机制来表明资源被几个指针共享。可以通过成员函数use_count()来查看资源的所有者个数。除了可以通过new来构造,还可以通过传入auto_ptr, unique_ptr,weak_ptr来构造。当我们调用release()时,当前指针会释放资源所有权,计数减一。当计数等于0时,资源会被释放。
shared_ptr 是为了解决 auto_ptr 在对象所有权上的局限性(auto_ptr 是独占的), 在使用引用计数的机制上提供了可以共享所有权的智能指针。
成员函数:
use_count 返回引用计数的个数
unique 返回是否是独占所有权( use_count 为 1)
swap 交换两个 shared_ptr 对象(即交换所拥有的对象)
reset 放弃内部对象的所有权或拥有对象的变更, 会引起原有对象的引用计数的减少
get 返回内部对象(指针), 由于已经重载了()方法, 因此和直接使用对象是一样的.如 shared_ptr sp(new int(1)); sp 与 sp.get()是等价的
weak_ptr 是一种不控制对象生命周期的智能指针, 它指向一个 shared_ptr 管理的对象. 进行该对象的内存管理的是那个强引用的 shared_ptr. weak_ptr只是提供了对管理对象的一个访问手段。weak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少。weak_ptr是用来解决shared_ptr相互引用时的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能下降为0,资源永远不会释放。它是对对象的一种弱引用,不会增加对象的引用计数,和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得shared_ptr。
class B;
class A
{
public:
shared_ptr pb_;
~A()
{
cout<<“A delete\n”;
}
};
class B
{
public:
shared_ptr pa_;
~B()
{
cout<<“B delete\n”;
}
};
void fun()
{
shared_ptr pb(new B());
shared_ptr pa(new A());
pb->pa_ = pa;
pa->pb_ = pb;
cout<
int main()
{
fun();
return 0;
}
可以看到fun函数中pa ,pb之间互相引用,两个资源的引用计数为2,当要跳出函数时,智能指针pa,pb析构时两个资源引用计数会减一,但是两者引用计数还是为1,导致跳出函数时资源没有被释放(A B的析构函数没有被调用),如果把其中一个改为weak_ptr就可以了,我们把类A里面的shared_ptr pb_; 改为weak_ptr pb_; 运行结果如下,这样的话,资源B的引用开始就只有1,当pb析构时,B的计数变为0,B得到释放,B释放的同时也会使A的计数减一,同时pa析构时使A的计数减一,那么A的计数为0,A得到释放。
注意的是我们不能通过weak_ptr直接访问对象的方法,比如B对象中有一个方法print(),我们不能这样访问,pa->pb_->print(); 英文pb_是一个weak_ptr,应该先把它转化为shared_ptr,如:shared_ptr p = pa->pb_.lock(); p->print();
https://www.nowcoder.com/tutorial/93/a34ed23d58b84da3a707c70371f59c21
智能指针的举例子
https://www.cnblogs.com/inception6-lxc/p/8597326.html
https://blog.csdn.net/zxxkkkk/article/details/109363441
https://blog.csdn.net/u011109881/article/details/80379505
https://blog.csdn.net/z_ryan/article/details/78760944?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight
MySQL中四种常用存储引擎的介绍
1>.InnoDB支持事物,而MyISAM不支持事物
2>.InnoDB支持行级锁,而MyISAM支持表级锁
3>.InnoDB支持MVCC, 而MyISAM不支持
4>.InnoDB支持外键,而MyISAM不支持
5>.InnoDB不支持全文索引,而MyISAM支持。(X)
进程通信:
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。
IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC。
进程间的八种通讯方式
1.管道:速度慢,容量有限,只有父子进程能通讯。
2.消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题。
3.信号量:不能传递复杂消息,只能用来同步
4.共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存。
5.套接字: 可用于不同机器间的进程通信。
那种最快:
几种方式的比较:
管道:速度慢,容量有限
消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题。
信号量:不能传递复杂消息,只能用来同步
共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了一块内存的。
https://blog.csdn.net/guoxiang3538/article/details/79376191
如果多线程的程序运行结果是可预期的,而且与单线程的程序运行结果一样,那么说明是“线程安全”的。
虽然用户态下和内核态下工作的程序有很多差别,但最重要的差别就在于特权级的不同,即权力的不同。运行在用户态下的程序不能直接访问操作系统内核数据结构和程序,
当我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态,
选择第k大的数据
提示:函数的值是int 并且函数的返回值也是int
https://www.cnblogs.com/Benjious/p/11611431.html
虚拟内存
https://www.cnblogs.com/lustar/p/7689059.html
https://blog.csdn.net/oChangWen/article/details/5342330
C语言之const与define区别
修饰变量,使其不能被修改
修饰指针
http://blog.sina.com.cn/s/blog_a2a6dd380102w73e.html
B树、B-树、B+树、B*树之间的关系
B树和B+树区别:
关键字数量不同:B+树分支结点M个关键字,叶子节点也有M个;B树分支结点则存在 k-1 个关键码
数据存储位置不同:B+树数据存储在叶子结点上;B树存储在每个结点上;
查询不同:B+树是从根节点到叶子节点的路径;B树是只需要找到数据就可以
分支节点存储信息不同:B+树存索引信息;B树存的是数据关键字
strcpy针对字符串
memcpy可以是数组、对象、字符串等,需要指定长度
重点在构造函数不同
重载
C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。
内存区域
new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。
https://blog.csdn.net/nie19940803/article/details/76358673
包括四大基本特征和五大基本原则。
特征:抽象、继承、多态、封装
原则:单一职责原则、开放封闭原则、替换原则、依赖原则、接口分离原则
面向对象的特征并简述
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求和保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不可抢占条件:进程已获得的资源,在末使用完之前,不能强行剥夺,只能在进程使用完时由自己释放。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
https://blog.csdn.net/weixin_41969690/article/details/107617634
https://my.oschina.net/alphajay/blog/5029
ALTER TABLE:添加,修改,删除表的列,约束等表的定义。
查看列:desc 表名;
修改表名:alter table t_book rename to bbb;
添加列:alter table 表名 add column 列名 varchar(30);
删除列:alter table 表名 drop column 列名;
修改列名MySQL: alter table bbb change nnnnn hh int;
修改列名SQLServer:exec sp_rename’t_student.name’,‘nn’,‘column’;
修改列名Oracle:lter table bbb rename column nnnnn to hh int;
修改列属性:alter table t_book modify name varchar(22);
C与C++的最大区别:在于它们的用于解决问题的思想方法不一样。之所以说C++比C更先进,是因为“ 设计这个概念已经被融入到C++之中
面向过程的语言:
优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展
面向对象的语言:
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护
缺点:性能比面向过程低
语法上:
C++具有封装、继承和多态三种特性
C++相比C,增加多许多类型安全的功能,比如强制类型转换、
C++支持范式编程,比如模板类、函数模板等
C语言和c++的区别
C语言中的struct与C++中的struct的区别表现在以下3个方面:
(1) C语言的struct不能有函数成员,而C++的struct可以有。
(2) C语言的struct中数据成员没有private、public和protected访问权限的设定,而C++ 的struct的成员有访问权限设定。
(3) C语言的struct是没有继承关系的,而C++的struct却有丰富的继承关系。
C语言中的struct是用户自定义数据类型,它是没有权限设置的,它只能是一些变量的集合体,虽然可以封装数据却不可以隐藏数据,而且成员不可以是函数。为 了和C语言兼容,C++中就引入了 struct关键字。C++语言中的struct是抽象数据类型 (ADT),它支持成员函数的定义,同时它增加了访问权限,它的成员函数默认访问权限为 public。
具体而言,在C++中,class和struct做类型定义时只有两点区别:
(1) 默认继承权限不同。class继承默认是private继承,而struct继承默认是public继承;
(2) class还用于定义模板参数,就像typename,但关键字struct不用于定义模板参数。
C++中基类的析构函数不是虚函数,会带来什么问题
https://blog.csdn.net/wangdd_199326/article/details/81324804
面试题:char * strcpy(char * strDest,const char * strSrc);
https://www.nowcoder.com/questionTerminal/8da86fee838348af931e2b86a2c160bc
修饰全局变量
修饰全局变量,不初始化默认初始为0,存储在静态存储区,从声明到程序结束一直存在
修饰局部变量
也存储在静态存储区,作用域是局部作用域,当定义他的函数或者语句块结束时,作用域结束,但该变量并没有被销毁,只不过我们不能访问,直到该函数再次被调用
修饰类的数据成员
不属于类的对象,类内声明,类外初始化,类的静态成员变量被所有对象共享,保证了共享性,又具备安全性
修饰类的成员函数
静态成员函数只能访问静态成员变量,不能访问非静态成员函数,原因是静态成员函数不与任何对象绑定,因此不包含this指针,在静态成员函数内部不能直接使用this指针,因此不能访问类的非静态成员变量
修饰函数
即静态函数,仅在声明它的cpp文件中使用,其他文件不可使用
面试例子
static关键字的作用,修饰函数有什么用?
加粗样式static修饰的函数叫静态函数,包括两种
静态函数出现在类里,则它是一个静态成员函数。静态成员函数不与任何对象绑定,因此不包含this指针,在静态成员函数内部不能直接使用this指针,即不能直接访问普通成员函数;静态成员函数属于类本身,在类加载时就会分配内存,可以通过类名直接去访问;虽然静态成员函数不属于类对象,但是可以通过类对象访问静态成员函数。
普通的全局的静态函数。限定在本源码文件中,不能在其他文件调用(普通函数的定义和声明默认情况下都是extern的,即可被其他文件调用)。故好处在于:1)其他文件中可以定义相同名字的函数。
IO多路复用(IO Multiplexing)
left join (左连接):返回包括左表中的所有记录和右表中连接字段相等的记录。
right join (右连接):返回包括右表中的所有记录和左表中连接字段相等的记录。
inner join (等值连接或者叫内连接):只返回两个表中连接字段相等的行。
full join (全外连接):返回左右表中所有的记录和左右表中连接字段相等的记录。
左连接 ,右连接,内连接和全外连接的4者区别
C++11并发学习之六:线程池的实现
线程池的原理及C++线程池的封装实现