C++基础(1)

一.C++介绍

本贾尼 斯特劳斯特卢普,于1979年4月贝尔实验室的本贾尼博士在分析UNIX系统内核流量分析时,希望有一种有效的更加模块化的工具
1979年10月完成了预处理器Cpre,为C增加了类机制,也就是面向对象,
1983年完成了C++的第一个版本,C with classes 也就是C++
C++与C的不同点:

1.C++完全兼容C的所有内容

2.支持面向对象编程思想

3.支持运算符,函数重载

4.支持泛型编程,模板

5.支持异常处理

6.类型检查严格

二.第一个C++程序

1.文件扩展名不同
		.cpp .cc .cxx .C
		
2.编译器
		g++ 大多数系统需要额外安装,ubuntu系统下的安装命令:
			sudo apt-get update
			sudo apt-get install g++
		gcc也可以继续使用但需要增加参数 -xC++ -lstdc++
	
3.头文件
		#include<iostream>
		#include<stdio.h>可以继续使用	
		#include<cstdio>也可以使用

4.输入/输出
		cout<<	输出数据
		cin>>	输入数据
		cout/cin会自动识别类型
		scanf/printf也可以使用

5.增加了名字空间
		std::cout
		using namespace std;
		所有的标准类型,对象,函数都在std命令空间			

三.名字空间

1.为什么需要名字空间
在项目中函数名,全局变量,结构,联合,枚举,类,非常有可能名字冲突,
而名字空间对这些命名进行逻辑空间划分(不物理单元划分),为了解决命名冲突

2.什么是名字空间
在C++中经常使用多个独立开发的库来完成项目,由于库的作者或开发人员根本没见过面,因此命名冲突在所难免,
C++之父为了防止命名冲突给C++设计一个名字空间的机制
通过使用namespace XXX把库中的变量,函数,类型,结构等包含在名字空间中,形成自己的作用域,避免名字冲突

		namespace xxx
		{
			}//没有分号

注意:名字空间也是一种标识符,在同一作用域下不能重名

3.同名的名字空间会自动合并(为了声明和定义可以分开写)
同名的名字空间如果有重名的依然会命名冲突

4.名字空间的使用方法
空间名::标识符//使用麻烦,但安全
::域限定符
using namespace 空间名;把空间中定义的标识符导入到当前代码中
不建议这样使用,相当于把垃圾分类后又倒入同一个垃圾车,依然会冲突

5.无名名字空间
不属于任何名字空间中的标识符,隶属于无名名字空间
无名名字空间中的成员使用::标识符 进行访问
如访问被屏蔽的全局变量

6.名字空间的嵌套
名字空间内部可以再定义名字空间,这种就叫名字空间嵌套
内层名字空间与外层的名字空间的成员,可以重名,内层会屏蔽外层的同名标识符
多层名字空间在使用时逐层分解

		n1::n2::n3::num;
		namespace n1
		{
			namespace n2
			{
			}
		}		

7.可以给名字空间取别名
由于名字空间可以嵌套,这样就会导致在使用内层成员时过于麻烦,可以给名字空间取别名来解决这类问题
namespace n123=n1::n2::n3;

四.C++的结构

1.不再需要 typedef,在定义结构变量时,可以省略 struct 关键字

2.成员可以是函数(成员函数),在成员函数中可以直接访问成员变量,不需要.或->,但是C的结构成员可以是函数指针

3.有一些隐藏的成员函数(构造,析构,拷贝构造,赋值构造)

4.可以继承,可以设置成员的访问权限,(面向对象)

五.C++的联合

1.不再需要 typedef,在定义联合变量时,可以省略 union 关键字
2.成员可以是函数(成员函数),在成员函数中可以直接访问成员变量,不需要.或->
3.有一些隐藏的成员函数(构造,析构,拷贝构造,赋值构造)

六.C++的枚举

1.定义,使用方法与C语言基本一致
2.类型检查比C语言更严格

七.C++的布尔类型

1.C++中有真正的布尔类型,bool是C++中的关键字,而c语言中不是
2.在C++中,true false 是关键字,而C语言中不是
3.在C++中,true false 是1字节,而在C语言中是多字节

八.C++的void*

1.C语言中void可以与任意类型指针自动转换
2.C++中void
不能给其他类型的指针直接赋值,必须强制类型转换,但其他类型的指针可以自动给void赋值
3.C++为什么这样修改void
?
为了更安全,所以C++类型检查更加严格
C++可以自动识别类型,对万能指针的需求不再那么强烈

九.操作符别名

某些特殊语言的键盘上没有~,&符号,所以C++标准委员会为了让C++更具有竞争力,为这些符号定义了一些别名,让这些小语种也可以更加愉快的编写代码
and &&
or ||
not !

十.函数重载(重载,隐藏,覆盖)

1.函数重载
在同一作用域下,函数名相同,列表参数不相同的函数,构成重载关系

2.重载实现的机制
c++代码在编译时会把函数的参数类型添加到参数名中,借助这个方式来实现函数重载,
也就是c++的函数在编译期间经历换名的过程
因此,C++代码不能调用c函数(C语言编译出的函数)

3.extern “C” {}
告诉C++编译器按照C语言的方式声明函数,这样C++就可以调用C编译器编译出的函数的函数了(C++目标可以与C目标文件合并成可执行程序)
如果c想调用C++编译出来的函数需要将C++函数定义用extern "C"包括一下
注意:如果两个函数名真的一样,一定会冲突

4.重载与作用域
函数的关系共享发送在同一作用下,不同作用域下的同名函数,构成隐藏关系

5.重载解析
当调用函数时,编译器根据实参的类型和形参的匹配情况,选择一个确定的重载版本,这个过程叫重载解析
实参的类型与形参的匹配情况有三种:
1.编译器找到与实参最佳匹配函数,编译器将生成调用代码
2.编译找不到匹配函数,编译器将给出错误信息
3.编译器找到多个匹配函数,但没有一个最佳的,这种错误叫二义性
在大多数情况下编译器都能立即找到一个最佳的调用版本,当如果没有,编译就会进行类型提升,
这样被选函数中就可能具有多个可调用的版本,这样就可能产生二义性错误

6.确定重载函数的三个步骤
1.候选函数
函数调用的第一步就是确定所有可调用的函数的集合(函数名,作用域),该集合中的函数就是候选函数
2.选择可行函数
从候选函数中选择一个或多个函数,选择函数的标准是参数个数相同,而且通过类型提升实参可被隐式转换为形参
3.选择最佳匹配
优先选择每个参数都匹配的方案,其次是参数完全匹配的个数,再其次是浪费内存的字节数

7.指针类型也会对函数的重载造成影响
C++函数的形参如果是指针类型,编译时函数名会追加Px(x是任意类型)

十一.默认形参

1.在C++中函数的形参可以设置默认值,调用函数,如果没有提供实参,则使用默认形参

2.如果形参只有一部分设置了默认形参,则必须靠右排列

3.函数的默认形参是在编译阶段确定的,因此只能使用常量,常量表达式,全局变量作为默认值

4.如果函数的声明和定义需要分开,只需要在函数声明中设置默认参数即可

5.默认形参会对函数重载造成影响,设置默认形参时一定要慎重

十二.内联函数

1.普通函数调用时是生成调用指令(跳转),然后当代码执行到调用位置时跳转到函数所在的代码段中执行

2.内联函数就把函数编译好的二进制指令直接复制到函数的调用位置

3.内联函数的优点就是提高程序的运行速度(因为没有跳转,也不需要返回),但这样会导致可执行文件增大(冗余),也就是牺牲空间来换取时间

4.内联分为显式内联和隐式内联
显式内联:在函数前加 inline(C语言C99标准也支持).
隐式内联:结构,类中有直接定义的成员函数,则该类型函数就会被优化成内联函数

5.宏函数在调用时会把函数体直接替换到调用位置,与内联函数一样也是使用空间来换取时间,所有宏函数与内联的区别(优/缺点)?
1.宏函数不是真正的函数,只是代码替换,不会有参数压栈,出栈,以及返回值,也不会检查参数类型,因此所有类型都可以使用,但这样会有安全隐患
2.内联函数是真正的函数,被调用时会进行传参,会进行压栈,出栈,可以有返回值,严格检查参数类型,但这样就不能通用,如果想被多种类型调用需要重载

6.内联适用的条件
由于内联会造成可执行文件变大,并增加内存开销,因此只有频繁调用的简单函数适合作为内联函数
调用比较少的复杂函数,内联后并不显著提高性能,不足以抵消牺牲空间带来的损失,所以不适合内联
带有递归特性和动态绑定特性的函数,无法实施内联,因此编译器会忽略声明部分的inline关键字

十三.引用

引用就是取艺名

1.引用的基本特性
引用就是取别名,声明一个标识符为引用,就表示该标识符是另一个对象的外号
1.引用必须初始化,不存在空引用,但有悬空引用(变量死了,名字还留着)
2.可以引用无名对象和临时对象,但必须使用常引用
3.引用不能更换目标
引用一旦完成了定义和初始化就和普通变量名一样了,它就代表了目标,一经引用终身不能引用其他目标

2.引用型参数
引用当作函数的参数能达到指针一样的效果,但不具备指针的危险,还比指针方便
引用可以非常简单实现函数间共享变量的目的,而且是否使用引用由被调函数说了算
引用当作函数的参数还能提高传递参数效率,指针至少还需要4字节内存,而引用只需要增加一条标识符与内存之间的绑定(映射)

3.引用型返回值
不要返回局部变量的引用,会造成悬空引用
如果返回值是一个临时值(右值),如果非要使用引用接收的话,必须使用常引用
注意:C++中的引用是一种取别名的机制,而c语言中的指针是一种数据类型(代表内存编号的无符号整数)

十四.c++的内存管理

1.new/delete C++中具备申请/释放堆内存功能的运算符
		相当于C语言在的malloc和free
		new    类型:会自动计算类型所需要的字节数,如果然后从堆分配对应字节数的内存,并返回内存的首地址(具备类型)
		delete 指针:会自动释放堆内存
		注意: new/delete 不能和 malloc/free 混用,因为newdelete会自动调用类,结构的构造函数,析构函数
		
2.数组的分配与释放
		new 类型[n];  	n表示数组长度,如果类,结构会自动调用n次构造函数
		delete[] 指针;	通过new[]分配的内存,必须通过delete[]释放
		new[]返回值前4个字节存放着数组的长度	

3.重复释放		
		delete/delete[]不能重复释放同一块内存
		delete/delete[]释放野指针的后果不确定,但释放空指针是安全的
	
4.内存分配失败
		当分配的内存过大,没有能满足需求的整块内存就会抛出异常std::bad_alloc
		new/delete与c语言的malloc/free的相同点和不同点?
		不同点
		身份:     运算符,      		标准库函数
		参数:	 类型(自动计算),		字节数(手动计算)
		返回值	 带类型的地址,		void*地址
		调用构造	 自动调用				不能调用构造/析构函数
		出错:	 抛异常				返回NULL
		
相同点:
			1.都能管理堆内存
			2.不能重复释放,
			3.可以释放空
	
注意:在C++中尽量使用 引用,new/delete	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值