赞
踩
第一个作用是隐藏:变量或者函数被static关键字修饰后只能在本程序使用(非static的可以通过extern关键字声明后在其他文件中定义,此文件可以调用)
第二个作用是指定变量存储位置:static变量存储位置位于全局数据区
第三个作用是默认初始化为0,被static修饰的变量默认初始化为0.
第四个作用是定义类中的静态成员变量,使得其属于类但不属于某个实例,类中声明,类外定义,不分配内存
第五个作用是定义类中的静态成员函数,使得其只能调用本类的静态成员变量/函数,因为非static成员函数和变量在类成员函数中调用时,由形参中隐含一个指向当前实例对象的this指针调用,静态成员函数没有this形参。
主要作用:用于标识该函数或者变量在别的文件中定义,提示编译器遇到此变量或者函数时就去别的模块寻找。可以用于链接指定。
最主要的区别是C是面向过程:分析解决问题的步骤,用函数实现步骤;C++是面向对象:把构成问题的事务分解成各个对象,建立对象,描述某个事务在解决整个问题步骤中的行为
C主要用于嵌入式领域、驱动开发等与硬件打交道,C++主要用于应用层开发,用户界面开发等与操作系统。
C++继承了C的底层操作特性
map<string, int> m{{"a", 1}, {"b", 2}, {"c", 3}};
for (auto p : m){
cout<<p.first<<" : "<<p.second<<endl;
}
vector<int> vec;
for(int i=0;i<10;++i)
{
vec.push_back(i);
}
for_each(vec.begin(),vec.end() ,[](int i)->void{ cout << i <<" "; }); // lambda表达式
- int arr[3]{1, 2, 3};
- vector<int> iv{1, 2, 3};
- map<int, string>{{1, "a"}, {2, "b"}};
- string str{"Hello World"};
多态作为面向对象的三大特性‘封装、继承、多态’之一,由虚函数机制实现,多态指相同的接口,不同的实现方式,特指父类指针调用函数时,实际调用的是指针指向的实际类型的成员函数。
虚函数由虚函数表实现
构造函数不能是虚函数:因为虚函数是由虚函数表实现,虚函数表需要一块内存,构造函数未构造没办法做到。
析构函数需要是虚函数:因为如果析构函数不是虚函数,在释放子类对象内存时,通过基类指针释放时,会调用基类对象的析构函数,达不到子类对象释放内存的目的。
函数指针与指针函数:int (*f)(int a, int b)、int *f(int a, int b)
智能指针的出现是为了更好地管理动态内存,防止忘记释放动态内存或者尚有指针引用内存的情况下释放内存。
https://www.cnblogs.com/hellogiser/p/fork.html
通过系统调用创建一个与原来进程完全一致的进程,两个进程可以做完全一样的事,但是如果初始参数不一样或者传入变量不同,可以做不同的事;一个进程调用fork后,系统先给新进程分配资源。例如存储数据和代码空间,然后把原来进程所有值都复制到新进程中,少量数值不同,相当于克隆。
fork仅仅被调用一次,却能够返回两次(一次是子进程返回,另一次是父进程返回),有可能有三种不同的返回值
fork出错的原因:进程数达到系统规定上限、系统内存不足
静态函数不能够作为虚函数被调用,因为首先,静态成员函数不属于任何类对象和类实例,所以加上virtual关键字没有意义;
然后静态成员函数没有this指针,而虚函数是靠虚函数表和指向表的指针实现的,必须考this指针访问,所以静态成员函数不能是虚函数。
虚函数的调用关系:this -> vptr -> vtable ->virtual function。
定义一个类,然后定义构造函数,接着构造一个全局变量为该类的一个实例,那么在运行main函数之前就会调用构造函数。
https://www.cnblogs.com/QG-whz/p/4472566.html
run time type identification运行时类型识别,dynamic_cast和typeid关键字会用到这个机制
容器的insert和erase操作可能会使得迭代器失效
vector:insert操作,只有在改变了内存大小的情况下会全部迭代器失效,否则只失效之后的迭代器,erase操作被删除节点后的所有节点的迭代器失效
list:insert操作不会使得迭代器失效,erase操作有且只有被删除节点的迭代器失效
map、set:insert操作不会使得迭代器失效,erase操作有且只有被删除节点的迭代器失效
有序、不重复的容器,不能直接修改set里的元素值,因为修改后不会自动排序,若要修改,必须删除后重新插入达到目的
- #include <iostream>
- #include <set> //使用set须包含此文件
- using namespace std;
- int main()
- {
- typedef set<int>::iterator IT;
- int a[5] = { 3,4,6,1,2 };
- set<int> st(a,a+5); // st里是 1 2 3 4 6
- pair< IT,bool> result;
- result = st.insert(5); // st变成 1 2 3 4 5 6
- if(result.second) //插入成功则输出被插入元素
- cout << * result.first << " inserted" << endl; //输出: 5 inserted
- if(st.insert(5).second)
- cout << * result.first << endl;
- else
- cout << * result.first << " already exists" << endl;
- //输出 5 already exists
- pair<IT,IT> bounds = st.equal_range(4);
- cout << * bounds.first << "," << * bounds.second ; //输出:4,5
- return 0;
- }
每个元素包括key和value两部分,按照key排序,所以不能直接修改key值,
- #include <iostream>
- #include <map> //使用map需要包含此头文件
- using namespace std;
- template <class T1,class T2>
- ostream & operator <<(ostream & o,const pair<T1,T2> & p)
- { //将pair对象输出为 (first,second)形式
- o << "(" << p.first << "," << p.second << ")";
- return o;
- }
- template<class T>
- void Print(T first,T last)
- {//打印区间[first,last)
- for( ; first != last; ++ first)
- cout << * first << " ";
- cout << endl;
- }
- typedef map<int,double,greater<int> > MYMAP; //此容器关键字是整型,元素按关键字从大到小排序
- int main()
- {
- MYMAP mp;
- mp.insert(MYMAP::value_type(15,2.7));
- pair<MYMAP::iterator,bool> p = mp.insert(make_pair(15,99.3));
- if(!p.second)
- cout << * (p.first) << " already exists" << endl; //会输出
- cout << "1) " << mp.count(15) << endl; //输出 1) 1
- mp.insert(make_pair(20,9.3));
- cout << "2) " << mp[40] << endl;//如果没有关键字为40的元素,则插入一个
- cout << "3) ";Print(mp.begin(),mp.end());//输出:3) (40,0)(20,9.3)(15,2.7)
- mp[15] = 6.28; //把关键字为15的元素值改成6.28
- mp[17] = 3.14; //插入关键字为17的元素,并将其值设为3.14
- cout << "4) ";Print(mp.begin(),mp.end());
- return 0;
- }
https://blog.csdn.net/changyang208/article/details/78668462
对齐、最后大小为最长变量所占大小的整数倍
宏定义的出现是因为考虑到函数调用花费空间与时间,宏定义只是在预编译阶段将代码段进行替换,不需要额外的空间和时间,但是容易产生二义性。
#define TABLE_MULTI(x) (x*x),在TABLE_MULTI(10+10)的输出结果是10+10*10+10,违背了我们的预期
#define TABLE_MULTI(x) ((x)*(x)),在TABLE_MULTI(a++)的输出结果是(a++)*(a++),即使加上了括号也不合预期输出。
所以引入inline内联函数,去代替宏定义
两者的区别在于:宏定义在预处理阶段展开,内联函数在编译阶段处理;内联函数是函数,但是没有参数压栈,但是有参数检查,宏定义没有参数检查,所以内联函数更加安全;但是内联函数的函数体不能过大,否则编译器会将内联函数看出普通函数来处理。
进程是资源分配的基本单位,线程是CPU调度和分派的基本单位,协程是用户态的轻量级线程
进程与线程:
线程和协程:
同步:在发出一个功能调用后,没有得到结果,不会返回,也就是说必须等待上一步执行完毕才会执行下一步,
异步:当一个异步过程调用时,调用不能立即得到结果,可立即执行下一步操作。
并发:几个程序在同一个CPU上执行,同时只能有一个程序执行;
并行:几个程序在几个CPU上执行,同时有多个程序在多个CPU上执行,互不干扰
同步是一种合作关系,为了完成某种任务而建立的多个进程或者线程的协调调用、次序等待,相互告知资源占用情况
互斥是一种制约关系,一个进程或者多个进程进入临界区会进行加锁操作,此时其他进程无法进入临界区,直到解锁
进程间同步和互斥方式:信号量、管程(将共享变量及操作集中在一个模块)、
线程间同步方式:信号量、互斥量、事件
https://blog.csdn.net/cl_linux/article/details/80328608
定义:多个进程因为资源竞争造成的相互等待
原因:系统资源不足、进程间的推进顺序不对
四个条件:
死锁处理:
https://blog.csdn.net/lzuacm/article/details/52853194
vector<int> myVec;
myVec.reserve( 100 ); // 新元素还没有构造
// 此时不能用[]访问元素
for (int i = 0; i < 100; i++ )
{
myVec.push_back( i ); //新元素这时才构造
}
myVec.resize( 102 ); // 用元素的默认构造函数构造了两个新的元素
myVec[100] = 1; //直接操作新元素
myVec[101] = 2;
reverse是容器预留空间,调用之后,并没有创建新对象,在加入元素时,需要调用push_back或者insert;
resize是改变容器大小,调用之后,已经创建了新对象,可以直接用[]访问。
#define ***
...
#endif
受C语言标准,依赖于宏名字不能重复,所以不仅保证同一文件不会被包含多次,而且内容一样的文件也不会被包含,但是 如果不同文件的宏名一样,就会出现编译器说找不到头文件声明的情况
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。