目录
当我开始学习c++,就被这门强大的语言震慑,心知学习道路之长。为学习C++就回到它的诞生之初,了解它的过往。
C++发展:
20世纪70年代中期,本贾尼博士希望开发一个既要兼容、稳定、实用的语言。以C语言为背景,以Simula思想为基础的语言,正好符合斯特劳斯特卢普的初衷和设想。(Simula 67是Simula语言的一种变种,被公认是首款支持面向对象的语言。)1979年,本贾尼·斯特劳斯特卢普到了AT&T贝尔实验室,开始从事将C改良为带类的C(C with classes)的工作,1983年,该语言被正式命名为C++。
1998年,C++的ANSI/IS0标准C++98(C++标准第一个版本,以模板方式重写C++标准库,引入了STL(标准模板库))被投入使用。随后又产生了C++ 03,C++ 11(增加许多特性,重要标准),C++ 14,C++ 17,C++ 20五个标准。
相比C,C++新增了31个关键字,如下:
命名空间
名称,存在于变量,函数,结构体,类及类的成员等等,随着项目的增大或者使用多个厂商的库时,名称冲突很可能存在,为了解决这个问题,C++引入了命名空间。
用namespace 名称{ }创建命名空间,有三种访问命名空间名称的方式。
namespce abc{
int a;//定义变量
void fun(){...} //定义函数
struct Node
{ //定义结构体
int val;
struct Node*p;
}
namespace abcd
{ //创建命名空间
}
}
1. ::域解析运算符
命名空间加::,使用命名空间中的名称。直接::则是使用全局命名空间中的名称。(区别于定义的命名空间,全局变量都在全局名称空间中)
abc::a=100;
abc::fun(){...}
abc::Node n1;
2.using声明和using编译指令
using 声明将特定的名称加入到所属的声明区域中。如果再函数外面使using声明,将把名称加入到全局名称空间中。
例如:
int a;
int main()
{
using abc::a; 将名称a加入到main的声明区域中,全局变量a被覆盖
// double a; err,已经有了a
return 0;
}
using编译指令:
例如 :
using namespace std; 将std命名空间中所有名称在全局中可用
int main()
{
using namespace abc; 将abc命名空间中所有名称在main函数中可用
return 0;
}
使用using声明更安全因为using编译指令导入了命名空间中所有的名称,使用域解析运算符::和using声明更安全(优先声明在局部而非全局)。
如果在源文件多个地方或多个源文件中定义了同名的命名空间,它们将被合并。
未命名的命名空间,就像后面直接带上了using编译指令,因为没有名字,不能在其他文件使用,内部的变量也是只有内部链接属性的静态变量。
例如:
static int a;
等价于
namespace {
int a;}
默认参数
或称缺省参数,就是给函数一个默认值,在函数的设计时更便捷。带默认值参数的函数,有默认值的参数需从右到左连续。在不传递实参时,形参将使用默认值。
例如,打印字符串的前n个字符函数:
函数重载
所谓函数重载是支持相同函数名的函数定义或声明,这便于实现相同的功能的函数编写,要求是函数参数的个数不同,或者类型不同,或者顺序不同(参数名不同,或者返回值类型不同不构成重载)。
C++相比C语言,支持函数重载,原因在于两者的函数名修饰规则不同,C语言下相同函数名的函数在预处理和编译后形成的汇编代码相同,C++则不同,如下(在Linux下的g++演示):定义了一系列的同名函数,
经过
编译成汇编代码 ,用grep 查找文本内容如下:看见以上五个同名函数被修饰成了五种不同的函数名,这样在链接阶段,通过不同的函数名重定位相应的函数地址,从而区分了同名函数。
extern "C"
C++兼容C,但是因为函数名的修饰规则不同,C++不能直接调用C编写的函数,在函数前加上extern “C”告诉编译器,这个函数要按C的规则来编译,这样才能调用用C写的函数。例如:工作目录下有三个文件cpp.cpp,test.h和test.c。在test.h和test.c下分别声明和定义了一个的函数。
在cpp.cpp文件下直接调用是会报错的:
用extern “C”告诉编译器按C的修饰规则来查找函数,则可以正常使用了。
引用
C++新增了一种复合类型是引用,引用是为存在的变量起一个别名,故引用的对象唯一,一旦指定后不可更改,改变引用就相当于改变变量本身,一个对象可有多个引用。
创建引用变量:
int a=100;
int &b=a;//为变量a起一个别名为b,
b++;//改变b将改变a
注意:int &b;err,引用必须初始化
const
const修饰的变量不可改变,视为常量。
const int a=100;
const int k;err,未初始化的常量
const的引用:
const修饰的引用与原来定义的变量相较,权限平移或缩小,(权限平移:属性不变;权限缩小:本为变量,现为常量)
int a=10;
const int &b=a;权限缩小,b将不可改变,a可以
const int a=10;
const int &b=a;权限平移,a,b都不可改变
const int &c=100;正确,常量引用,权限平移
int &d=c;err,权限放大
double pi=3.14;
const int &p=pi;
int &p0=pi;//err,权限放大。
编译会将代码转为:
const int temp=pi;
const int &p=temp;借助临时变量(具有常属性),权限平移
因为引用的底层实现是指针,故引用的效率和传址效率一般高,只不过解引用过程由编译器做了。
指针和引用的比较:
1.有空指针,无空引用,引用的对象是唯一存在的,故引用比指针更安全,但是也没指针灵活。
2.在sizeof中,引用结果为引用类型的大小,而指针始终为地址所占空间大小。
3.有二级指针,无二级引用。