c++入门
话不多说先看一段代码
#include<iostream>
using namespace std;
int main()
{
cout<<"hello world"<<endl;
return 0;
}
我的老师在c++入门的时候经常说的一句话,“有的同学,可能c++课都上完了竟然不知道开头两句代码到底是用来干嘛的,这真的是很可惜的一件事情......“
#include<iostream>,这跟c语言的包含头文件非常相似,其实也就是一种库,iostream,输入输出流,什么叫流,计算机中的术语,一串连续的数据集合
cout:c++输出函数
endl:理解为换行符
<<:流插入运算符
至于上面的第二段代码就需要详细解释了
命名空间
我们在定义标识符的时候,不会随意采用标识符,相反我们会采用有意义的英文标识符,但也就是因为有意义,当面临多人协作开发,或者自己遇到多个问题但是类似,需要用到相同的名称时,在c语言角度就会面临重定义问题。所以为了解决这个问题,提出了命名空间。
namespace hjw
{
int rand=xxx;
}
定义属于自己的专属命名空间,当然也可以根据需求灵活选择
核心 namespace 名字{ }
需要注意的是如果你想要引用变量rand,比如要hjw::rand;每一个变量都需要展现其命名空间,这样编译器才知道要去哪里寻找。同样,这样也有一个问题就是太麻烦了,我每次引用这个变量都需要标识命名空间,显得非常冗余,所以就有了接下来的几个操作。
1、命名空间展开
using namespace std;
这句代码的意思就是把std的命名函数、变量全部展开,调用std标准库函数的时候不再需要标识命名空间。
2、命名空间部分展开
using std::cout;
这样在调用cout函数的时候就不再需要标识命名空间。
这里有一个思想,之所以有命名空间,就是为了防止命名冲突,虽然不可避免会造成使用上的麻烦,但是为了安全着想。所以实际操作的时候,我们会暴露常用的函数,或者直接暴露整个std库,但注意这也仅仅是在日常代码、习题练习的时候,做项目还是建议老老实实标识命名空间域。
缺省参数
void func(int a=0)
{
cout<<a<<endl;
}
缺省参数实际操作就是在定义形参的时候直接给一个值,能够实现的功能就是,如果你实参传值了,那么就用实参的值,如果你没有传值,就默认用缺省参数。这主要是为了处理你不知道实参该传多少。比如c语言实现的那个通讯录,假如你不知道一开始要传4个还是8个还是多少多少,你就可以完全不用管,用一个缺省参数,后面空间不够了再扩容就行了。
缺省参数规则:
1、缺省参数必须从右边开始缺
2、必须连续缺省不能跳跃缺省
3、传参,默认从左开始传,不能跳跃传参
比如上面全缺省参数函数,你不能TestFunc(,2,)这么传参
温馨提示:如果涉及到声明跟定义分离时,缺省参数默认在声明的地方缺省,编译器不接受定义缺省参数。
函数重载
c语言是不允许同名函数存在的,比如你像这种交换函数,有整数、浮点数,在c语言中不同类型要写一个不同的函数,所以就需要不同的函数。在c++中允许同名函数,但是也有对应的要求--参数类型不同,可以有不同类型的参数,也可以不同顺序类型的参数
double x(int y,double z);
double x(double y,int z);
这也是可行的
这个功能有一个非常巧妙地地方在于,有时候我们需要同名函数处理不同情况的问题,比如同样是一个交换函数,整型变量之间的交换,浮点型变量之间的交换......,在c语言里,不同类型的交换函数我们需要不同的函数,但在c++,我们可以通过改变参数来实现函数重载,一个函数名解决各种类型变量的问题。
c++是如何支持函数重载的呢?
首先链接有一个非常重要的过程,并不单单是合并,它需要找一些只给了声明函数变量的地址。其次.o文件会有一个符号表,这里就是各种修饰过的函数名,当然会根据对应的函数名修饰规则。
函数名修饰规则:参数不同,修饰出来的名字就不同了。不同编译平台修饰的不一样。
linux中,参数类型不同,参数顺序不同,就会有不一样的函数名字,然后编译器能够分别。
上图就是linux下函数的修饰名
引用
int a=10;
int& b=a;
&:引用操作符,好吧可以看到&其实有多种意思,这里又充当了引用操作符
引用就像是起别名,上述代码我给a起了另外一个名字叫做b,a跟b其实指的是同一个东西,我并没有给b开辟空间,只是给a开辟了空间,然后b也指向、代表这块空间。从底层实现逻辑来说的话,引用跟指针是一样的。
引用的特性:
1、引用必须初始化
2、引用不能更改
3、一个变量可以存在多个引用
引用的使用场景
swap(int& a,int& b)
{
int tem=a;
a=b;
b=tem;
}
一个平平无奇简简单单的交换函数,使用别名之后,形参就是实参的别名,改变了形参就是改变形参,跟指针效果一致。
这样可以理解为不创建临时变量,如果涉及到大对象传参,可以提高效率
传引用返回:
引用示意图
//传引用返回
#define N 10
typedef struct ay
{//定义一个结构体类型
int a[N];
int size;
}ay;
int& re(ay& ray,int num)
{//传引用返回
int i = 0;
return ray.a[num];
}
int main()
{
int i = 0;
//定义结构体
ay ray;
for (i = 0; i < N; i++)
{//结构体赋值
re(ray,i) = i * 10;
//ray.a[i] = i * 10;
//上面两句代码作用是一样的,传引用返回相当于传了一个变量回来
}
for (i = 0; i < N; i++)
{
cout << re(ray, i) << " ";
}
cout << endl;
return 0;
}
内联函数
在c++的角度,宏是一个非常麻烦的东西,不确定性挺大的,所以创建了内联函数,简单来说就是函数的操作,宏的性质
宏缺点:
1、不能调试
2、没有类型的安全检查
3、有些场景非常复杂
inline int add(int x,int y)
{
int z=x+y;
return z;
}
给函数前面加一个inline就是内联函数了,当然这是一种建议,具体会不会执行看编译器
内联函数适合的是小函数,如果代码量太大了,就没啥内联与否了
内联函数不要声明和定义分离,分离会导致链接错误,因为内联函数不进符号表。
正常分离函数会有一个call指令,后期遇到了先记住这个位置的函数,然后再链接阶段去源文件把定义拿过来。但是内联函数没有call指令,遇到了就直接展开。所以用的时候直接.h定义就可以了
好啦,今天就到此为止吧~~