初识c++

初识C++

  • 命名空间
  • 缺省参数
  • 函数重载
    • c++支持函数重载原理
  • 引用
    • 常引用
    • 引用作用
    • 引用和指针的区别
  • 内联函数
  • auto关键字
    • auto的使用
  • 指针空值
  • 其他

命名空间

为了避免命名冲突和污染,c++提出了命名空间的概念,一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中,其用法为:

//定义了一个名为date的命名空间
namespace date
{
	//这里面正常定义变量,函数等成员即可
	int year=0;
	int month=0;
	int day=0;
	int fun1()
	{
		//...
	}
}

当我们想要使用某个已经定义好的变量或函数时,编译器默认是不会到命名空间中去寻找的,若我们想要用命名空间中的成员时,有三种方法:
①成员前加上命名空间名称及作用限定符:

int i=date::year;

②使用using将命名空间的某个成员引入:

using date::year;
int i=year;

③使用using namespace将命名空间引入:

using namespace date;
int i=year;
int j=month;
int k=date::day;

第②和③种方法本质都是将命名空间里面的成员暴露出来,使其暴露在using位置开始直至所在作用域结束的空间内(注意不是直接将命名空间里面的成员拿出来成为该作用域的成员)。

int main()
{
	using namespace date;
	int year=0;
	int i=year;//执行到这里year产生歧义。出错
}
int main()
{
	using namespace date;
	int year=0;
	//该代码不会报错
}
//命名空间里面的year虽然暴露出来了,但并没有报重定义错误

如果将命名空间里面的成员全部暴露出来,命名空间就失去了存在的意义,因此我们并不推荐将命名空间展开的方法。

最后还有2点:
1.如果在多个或一个文件里名字相同的命名空间会被合并。
2.std是c++标准库的命名空间,c++标准库的定义实现都放到了这个命名空间里面

缺省参数

c++允许我们在声明或定义函数时为函数的参数指定一个缺省值,当我们没有指定实参时会使用缺省值,改缺省值必须是常量或全局变量。
缺省值只能在函数声明的时候给

int Sum(int a=1,int b=2)
{
	return a+b;
}
int main()
{
	int sum1=Sum();//sum1=3
	int sum2=sum(3);//sum2=5
}

对于半缺省参数,要缺省的参数要放到没有缺省值的参数之后,传参时不能跳着传

//错误
void fun1(int num1=1, int num2, int num3=3, int num4=4)
{
	//...
}

//正确
void fun1(int num1, int num2=2, int num3=3, int num4=4)
{
	//...
}

int main()
{
	fun1(1,2,3)//正确传参:num1=1,num2=2,num3=3
	fun1(1,,,4)//想跳着传参,错误
}

函数重载

c++允许函数的名字相同,但参数要不同(参数类型、个数、顺序不同皆可)

int fun(int num1,float num2)
{
	//...
}
int fun(float num1,int num2)
{
	//...
}
//构成函数重载

c++支持函数重载原理

c语言在编译链接时,会生成一个函数名与地址一一对应的符号表,因此c语言通过函数名就可以找到函数地址,c++也是类似,只不过c++的符号表不是单纯的函数名与地址一一对应,以linux下的编译器为例(不同编译器处理方法不同,但大体相似),会按以下规则生成符号串:
-z+函数名字符个数+函数名+参数类型首字符

fun(int a,char b)//生成的符号串为:-z3funic

然后用该符号串与函数地址一一对应生成符号表,由于函数参数不同,符号串具有唯一性,寻找函数地址时不会产生歧义,这就允许了函数重载。

引用

c++允许为一个已经存在的变量取别名,编译器不会为引用变量再开辟一块空间,而是与被引用的变量共用一块空间。

int mian()
{
	int a=1;
	int &b=a;//引用
	b++;
	cout<<"a="<<a;//a=2;
}

引用特性
①引用在定义时必须初始化
②一个变量可以有多个引用
③一旦引用一个实体,引用的指向不在改变

int main()
{
	int a=1;
	int b=2;
	int&c=a;
	c=b;//不是将c的引用改为b,而是赋值,a=2;
}

常引用

对于常引用,我们只需要知道权限只能平移或缩小,不能放大

int main()
{
	const int a=10;
	const int &b=a;//正确
	int &b=a;//错误,a为常量,b为变量,权限放大
	
	int c=10;
	const int&d=c;//正确,权限可以缩小
	
	const int& e=10;//正确
	//int& e=10;错误
}

在有类型转换时,编译器会生成一个临时常量,再将其赋给左操作数

int main()
{
	double a=1.1;
	int& b=a;//出错
	const int&b=a;//正确
}

引用作用

1.用于参数

void Swap(int& a,int& b)
{
	int temp=a;
	a=b;
	b=temp;
}

int main()
{
	int a=1;
	int b=2;
	Swap(a,b);//a=2,b=1
}

2.用于返回值
如果函数返回时,出了函数作用域,要返回的对象还在,可以使用引用返回,否则只能使用传值返回。

int& fun()
{
	static int a=1;
	return a;
}

使用引用返回可以提高函数返回时的效率

引用和指针的区别

1.引用是一个已经存在的变量的别名,指针是存储变量的地址
2.引用在使用时必须初始化,指针没有要求
3.一旦引用一个实体,引用的指向不在改变,指针可以在任何时候改变指向
4.没有NULL引用,但有NULL指针
5.在sizeof中的意义不同:引用的结果是引用变量的大小,指针结果为地址空间的大小(4/8字节)
6.引用自加加是实体加1,指针自加加是指针向后偏移一个类型的大小
7.有多级指针,没有多级引用
8.访问实体时,对于引用编译器自己处理,指针需要显示解引用
9.引用比指针使用起来相对更安全

内联函数

宏有许多缺陷,使用起来容易出错,关于宏的介绍,c++喜欢用enum、const代替宏常量,用内联函数代替宏函数

如果在函数前加上关键字inline,函数就会被改成内联函数,编译时c++会在调用内联函数的地方将其展开,没有了函数调用建立栈帧的开销,使程序的运行效率得到提升,但由于内联函数是直接将函数展开,这就使得目标文件变大,因此内联函数是一种空间换时间的做法
并不是加了inline编译器就会将函数作为内联函数,inline对于编译器来说只是一个建议,如果函数较小(只有几行)、频繁调用、不是递归则成为内联函数,否则编译器忽略inline特性。
内联函数不能声明和定义分离,因为内联函数是要展开的,没有生成符号表的必要,所以如果声明定义分离,编译器在链接时就会出错。

auto关键字

当我们在进行赋值操作时,我们需要清楚的知道右操作数的类型并要准确书写出来,但有时候做到这个很麻烦,因此c++提供了auto关键字,具有自动推导右操作数类型的功能。

int a=10;
auto b=a;//b为int型

auto并不是一种类型,只是一个类型声明的占位符,编译时编译器自动将auto替换成推导到的类型。

auto的使用

1.auto定义变量时必须初始化

auto a;//错误

2.在声明指针类型时,auto与auto*没有任何区别

int a=10;
auto b=&a;
auto* c=&a;
//b、c都是int*型

3.声明引用类型时必须加上&

int a=10;
auto& b=a;

4.一行声明多个变量时,这些变量类型必须相同
编译器只对第一个变量的类型进行推导,然后用推导出来的类型定义该行其他变量的类型,因此如果类型不同就会出错。

auto a = 10, b = 1.1;//出错

auto不能作为函数参数,函数返回值,也不能用来定义数组

void fun1(auto a)//错误
{
	//...
}

auto fun2()//错误
{
	//...
}

auto a[]={1,2,3};//错误

指针空值

c语言NULL指针的定义为0或无类型((void*)0)的指针,这就会存在一些问题,c++使用nullptr表示指针空值,为无类型(void*)0。

其他

当for循环迭代范围确定时,可以使用以下方法遍历数组

int main()
{
	int a[3]={1,2,3};
	for (auto& b:a)//将a数组的每个元素乘2
	{
		b*=2;
	}
}

void fun(int a[])//出错,迭代范围不确定
{
	for (auto& b:a)//将a数组的每个元素乘2
	{
		b*=2;
	}
}

cout和cin分别是ostream和istream类型的对象,<<是流插入运算符,>>是流提取运算符。

你可能感兴趣的:(c++,java,算法)