C++知识点总结
来源:互联网 发布:linux安装vftp 编辑:程序博客网 时间:2024/06/06 09:58
C++基础
- C++注重类型,进行严格的类型检查,在C++中,不同类型的指针不能直接赋值,必须强制转换;
- C语言的全局变量有声明和定义的差别,声明可以有多个,定义只能由一个,C++全局变量和静态全局变量没有声明和定义的差别;
- typeid(num).name();可以打印出num的数据类型;
decltype(num) numA(10);decltype可以将num的数据类型作为numA的类型; - 结构体和共用体
- 结构体内部成员变量可以有默认参数值,匿名结构体不允许初始化,结构体可以实现封装,继承,多态;
- union
- 本质是一个类,其内部可以有函数,内部数据是共享内存的,但是不能继承;
- union 具备结构体的所有功能;
- 内联函数
- 内联函数不能作为函数调用,而是直接把内联函数的代码嵌入到调用的语句中;
- 内联函数适合函数代码很少,并且频繁的大量调用;
- 内联函数只是对编译器的建议,函数声明为内联并不一定称为内联;
- 内联取代宏
- 内联函数在运行时可调试,而宏定义不可以;
- 编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义不会;
- 内联函数可以访问类的成员变量,而宏定义不能;
- 在类中声明同时定义的成员函数,自动转化为内联函数;
- 一般情况下,对内联函数做如下限制:
- 不能有递归,不能包含静态变量,不能包含循环;
- 不能包含switch和goto语句,不能包含数组;
引用
- 引用就是一个变量的别名,而不是地址;
- 引用作为函数的参数,没有出栈,入栈操作,所以效率更高;
- 左值和右值
- 左值是可以放在赋值号左边被赋值的值,必须在内存有实体,左值引用使用指针实现;
- 右值引用,可以节约内存拷贝,内存优化所必须,主要用在函数中较大的对象作为形参,形式: 类型 && 变量;
引用实例
- int (&ra)[10] (a) 引用一维数组
- int (&ra)[2][5] (a) 引用二维数组
通过函数改变函数指针,引用一个函数指针
void change(int (*&rp)(int a,int b)){ rp = jian; cout << rp(1, 2) << endl;}
返回一个函数指针的引用
int(**& changep(int(*&rp)(int, int)))(int, int) { rp = jian; return rp;}
- 引用的本质是指针,直接sizeof引用,就是求引用的数据的大小,代码区的函数不计入结构体的sizeof;
- const变量和函数
- const限定变量类型
- int const *p1,const int *p1;
p1指向常量的指针,指向的数据不可以修改,可以改变其指向的地址—>可读不可写权限; - int *const p1;
p1指向指针常量的指针,指针不可以修改,但是指针指向的变量的值可以修改—>可读可写权限; - const int * const p1;
p1指向的指针和指针指向的值都是常量,不可以修改;
- int const *p1,const int *p1;
- 函数的形参可以是const T& val,或者返回指向常量类型的指针,保证其使用或返回之后不会被修改;
- 对于const int a(10);这个变量是直接从常量表读取的,没有直接从内存读取,如果使用const_cast对其进行修改,则真实的内存已经修改,但是编译器会优化,不会从内存读取;
- const 动态监测类型,实现赋值,赋值会自动进行类型转换,避免类型不一致出错,const在内存有实体,有的编译器会直接获取常量的值进行替换;
- gcc 和 VC最新版本都是从代码区存储常量表,常量在寄存器产生,不会从内存读取,属于编译器的优化;
- const限定变量类型
- new 和 delete
- 基本概念
- new 和 delete是C++内建的操作符,不需要任何头文件,用new分配的数组必须用delete释放;
- 空类占一个字节,表示自己存在;
- 没有分配内存,构造和析构无意义;
- 全局的new和delete监视所有的释放和分配,局部的new 和 delete监视某个类的所有分配和释放;
- 局部的new 会调用全局的new,全局的new会调用malloc分配内存内存,之后会调用构造函数;delete时调用析构函数会先调用局部的delete,然后调用全局的delete,最后全局的delete调用free函数;
- 基本概念
- 函数重载和默认参数
- 函数的参数个数,参数的类型不同,参数的顺序不同,可以实现重载,重载与返回值无关;
- 函数指针没有默认参数,必须全部输入数据;
- 遇到具有相同非默认参数的函数无法调用时,可以通过定义函数指针指向不同的函数的形式进行调用;
- 函数的名称是一样的,但参数列表不同,可以实现重载;函数参数列表形同,但返回值不同,不可以实现重载;
- 函数重载与返回值类型无关;
函数模板与自动数据类型
带有多个参数的函数模板形式如下:
template<typename T>T sum(int count,T data1 ...){ va_list arg_ptr; //参数列表的指针 va_start(arg_ptr, count);//限定从count开始,限定多少个参数 T sumres(0); for (int i = 0; i < count; i++){ sumres += va_arg(arg_ptr, T); } va_end(arg_ptr);//结束 return sumres;}
auto与函数模板
//如果要使用函数模板,需要实例化即:函数名<实例化类型>(参数...);template<class T1, class T2>//根据类型获取类型auto get(T1 data, T2 bigdata)->decltype(data * bigdata){ return data * bigdata;}//decltype可以根据括号内的数据类型导出返回的数据类型,函数的参数不允许使用自动变量;
通用可变参数的函数模板
void showall(){}//空函数,接口,不能去掉,否则不能编译,最后结束递归template<typename T, typename...Args>void showall(const T &value, const Args &...args){ //Args通用的数据类型,加上const使数据不能修改,也可以加上引用 cout << value << endl; showall(args...);//继续传递,需要一个同名空函数结束递归} //调用方式如下:int num1 = 10, num2 = 9, num3 = 11;double db1 = 10.3, db2 = 20.3;char str[20] = "gsw";char ch = 'S';showall(num1,num2,num3);showall(db1, db2, num1, ch, str);
函数模板的重载
template<typename T>void showarray(array<T,10> myarray,int n){ cout << "TTTTT" << endl; for (int i = 0; i < n; i++){ cout << myarray[i] << '\t'; } cout << endl;}template<typename T>void showarray(array<T*, 10> myarray, int n){ cout << "T*T*T*T*T*" << endl; for (int i = 0; i < n; i++){ cout << *myarray[i] << '\t'; } cout << endl;}array<int, 10>intarray = { 1, 2, 3, 4, 5,6,7,8,9,10 };array<int *, 10>pintarray ;array<int **, 10>ppintarray;for (int i = 0; i < 10; i++){ pintarray[i] = &intarray[i];}for (int i = 0; i < 10; i++){ ppintarray[i] = &pintarray[i];}showarray(intarray, 5);showarray(pintarray, 5);showarray(ppintarray, 5);
类型转换
- static_cast
static_cast<需要转换的数据类型>(要转换的数据) (80%情况都是它),进行一般的数据类型转换; - const_cast
const int num(10); num可以修改,无法生效,编译时候无法从内存读取;
const int *p = num; 限定权限,只读不可写
const_cast用于去掉常量指针或引用的const属性 (5%) - reinterpret_cast
指针转换,强类型,类型决定了数据的解析方式 - dynamic_cast
用于指针之间的转换
- static_cast
新类型数组array
array数据类型,array<类型,数组大小>,初始化之后数组的大小不可以改变array<double, 3> dbnew={ 1.1, 2.2, 33.3 };
array<double, 3> dbnew1 = dbnew;//**可以实现数组之间的整体操作**
array<array<int, 5>, 3> myint4 = {myint1,myint2,myint3};//3*5 二维数组的声明方法函数包装器
- 设计通用的执行接口,接口可以设计关卡,计数
- 函数包装器依赖于函数模板,实现通用泛型
- 函数代码可以内嵌在另一个函数,实现函数代码的内嵌
//函数包装器,T是数据类型,F是函数;template<typename T, typename F>T run(T v, F f){//F是函数指针类型 static int count = 0; count++;//计数器 cout << "执行一个参数的函数包装器" << count << "次" << endl; if (count > 1){ T vx(0); return vx;//可以限定函数的执行次数 } return f(v);//函数传入参数}template<typename T, typename F>T run(T v1,T v2, F f){ return f(v1,v2);//函数传入参数}int cheng(int a, int b){ return a*b;}using std::function;//专门function<int(int, int)> fun4 = cheng;function<double(double)>fun1 = [](double u){return u * 2; };function<int(int, int)> fun3 = [](int u1, int u2){ return u1 + u2;};cout << run(num1, num2, cheng) << endl;cout << run(num1, num2, fun3) << endl;
仿函数
仿函数是早期的明明,C++标准所采用的新名称是函数对象。
仿函数其实就是一个“行为类似函数”的对象,其类别定义中必须自定义(或说改写,重载)function call 运算符(operator()),拥有这样的运算符之后,我们就可以在仿函数的对象后面加上一对小括号,调用仿函数所定义的operator();using namespace std::placeholders;//仿函数,创建一个函数指针,引用一个结构体内部或者一个类内部的公有函数struct mystruct{ void add(int a){ cout << a << endl; } void add2(int a,int b){ cout << a+b << endl; } void add3(int a, int b,int c){ cout << a + b+c << endl; }};//auto自动变量,地址,函数指针//第一个参数引用内部函数,第二个参数绑定一个实体对象,其他参数代表有多少个参数auto func = bind(&mystruct::add, &struct1, _1);auto func1 = bind(&mystruct::add2, &struct1,_1, _2);auto func2 = bind(&mystruct::add3, &struct1, _1, _2,_3);另一种方法mystruct struct1;//绑定机制,创建函数指针,数据私有,代码共享//函数通过调用,调用需要传递对象名,函数需要说明哪个对象才能调用void(mystruct::*p)(int a) = &mystruct::add;
using 别名
简写数据类型的时候尽量使用using,不要使用typedef;int add(int a, int b){ return a + b;}typedef int(*ADD)(int a, int b);using FUNC = int(*)(int a, int b);//别名机制namespace space{//隔离模板,避免冲突 template<class T> using ptr = T*;//模板的简写}using co = std::ios_base::fmtflags;//using 只可以简写数据类型//ADD p=add;//FUNC pa = add;space::ptr<int> pint(new int(3));cout << *pint << " "<<pint<<endl;
模板元编程
//斐波拉契数列 1 1 2 3 5 int getdata(int n){ if (n == 1 || n == 2) return 1; else return getdata(n - 1) + getdata(n - 2);}//模板元把运行时消耗的时间在编译期间优化template<int N>struct data{ enum a{ res = data<N - 1>::a::res + data<N - 2>::a::res };};template<>struct data<1>{ enum a{ res = 1 };};template<>struct data<2>{ enum a{ res = 1 };};int main(){ const int myint = 40; int num = data<myint>::res;//<>内部不可以有变量 std::cout << num << std::endl; std::cout << getdata(40) << std::endl; std::cin.get(); system("pause"); return 0;}
- 主要思想:
利用模板特化机制实现编译期条件选择结构,利用递归模板实现编译期循环结构,模板元程序则由编译器在编译期解释执行; 优劣及适用情况
通过将计算从运行期移至编译期,在程序启动之前做尽可能多的工作,最终获得速度更快的程序。
模板元编程的优势在于:- 以编译耗时为代价换来卓越的运行期性能(一般用于为性能要求严格的数值计算换取更高的性能)。通常来说,一个有意义的程序的运行次数(或服役时间)总是远远超过编译次数(或编译时间)。
- 提供编译期类型计算,通常这才是模板元编程大放异彩的地方。
缺点:
- 代码可读性差,以类模板的方式描述算法也许有点抽象。
- 调试困难,元程序执行于编译期,没有用于单步跟踪元程序执行的调试器(用于设置断点、察看数据等)。程序员可做的只能是等待编译过程失败,然后人工破译编译器倾泻到屏幕上的错误信息。
- 编译时间长,通常带有模板元程序的程序生成的代码尺寸要比普通程序的大,
- 可移植性较差,对于模板元编程使用的高级模板特性,不同的编译器的支持度不同。
- 主要思想:
静态断言
#define Mvoid main01()int num(10);//字节>4#ifdef Mstatic_assert(sizeof(num) >= 4, "fault ");#endif//调试代码,迅速知道代码错误在哪一行 cout << __FILE__ << endl;//指出所在文件cout << __LINE__ << endl;//提示所在行号cout << __DATE__ << endl;//源代码编译的时间cout << __TIME__ << endl;//当前的时间cout << __FUNCTION__ << endl;//显示函数名
类和面向对象
1. 面向对象
1. 类的继承实现代码重用;2. 类的封装: 1. 类的代码和数据一体化; 2. 代码的封装,限定谁可以执行,谁不可以执行; 3. 数据的封装,防止数据被意外修改;3. 类的多态,一个借口根据实际需求完成很多不同功能;
2. 友元
C++控制类对象私有部分的访问,但有时候需要在类外部访问类的私有成员,这种情况下C++提供了友元机制;1. 创建友元的步骤: 1. 将函数、类声明放在类的声明中,并在原型前加上关键字friend; friend 返回值 函数名称(参数列表); friend class classname; 2. 编写友元函数的定义,不需要在定义中使用关键字friend; friend 返回值 func_name(参数列表);2. 友元的性质 1. 友元函数不属于类; 2. 友元是单向的,没有传递性; 3. 友元函数可以访问类的私有变量,还可以访问私有函数; 4. 友元函数声明有friend,定义就不需要了,或者可以定义在类的内部;
3. 构造和析构函数
阅读全文
0 0
- C语言知识点总结
- C语言知识点总结
- C/C++ 知识点总结
- C语言知识点总结
- C语言知识点总结
- c知识点总结
- C语言知识点总结
- c知识点总结
- C语言知识点总结
- Objective-C 知识点总结
- C/C++ 知识点总结
- C语言知识点总结
- c语言知识点总结
- Objective-C知识点总结
- C语言知识点总结
- c知识点总结大全
- C语言知识点总结
- 【c++】c++知识点总结
- CAML
- 从Thread,ThreadPool,Task, 到async await 的基本使用方法解读
- check全选非全选
- JS 异常: Uncaught RangeError: Maximum call stack size exceeded
- Android 网络请求:Retrofit 使用
- C++知识点总结
- xxxx is deprecated
- springmvc报错 org.springframework.web.servlet.DispatcherServlet
- spring事务建言者创建类图
- Android中几种常用的定时器和延时方法
- 剑指offer_第一个只出现一次的字符
- 微变等效电路法
- ROS之topic和service通信比较
- Lua元表和元方法(转载)