初识C++

作用域

第一次接触C++相信大部分人都是会用到using namespace std;这句代码。就是命名空间,那么为什么会使用这个呢?首先我们先来了解一下作用域这个概念。然后再来说命名空间。

在C语言中,我们知道,有三个层次的作用域,即文件(编译单元),函数和复合语句。C++中又引用了类作用域,类是出现在文件内的。通俗点讲就是每个大括号范围内的内容就可以看作是一个域。在不同的作用域中可以定义相同名字的变量,他们是互不干扰的,系统可以识别。
在我们写程序的时候可以小心点就不会出现名字冲突的错误,但是一个软件大都是由多个人完成的。如果说A写了一个data1.h 在其中定义了类Data和Fun函数。而B写了一个data2.h 在其中也定义了类Data和Fun函数,但是内容与Data1.h中的不同。那么当主程序来引入这些.h文件,进行编译的时候就会出现名字冲突的问题。为了解决这个问题,所以就引入了命名空间这个概念。

什么是命名空间

命名空间实际上就是由程序设计者所命名的。。程序设计者可以根据需要需要指定一些有名字的的空间域,把一些全局实体放在各个命名空间,从而与其他全局实体分隔开来。

namespace A1
{
    int a = 2;
    int b = 3;
}

namespace 是命名空间的关键字,A1是这个命名空间的名字。这个名字可以由我们自己设定。注意a,b仍然是全局变量,只是这两个全局变量是定义在A1这个命名空间里的。这样就能解决名字冲突。因为在不同的命名空间里就算你定义相同的名字的变量也不会出现错误,因为使用时只需要加上命名空间的名字系统就可以做出区别。下面用代码举例。

#include<iostream>
using namespace std;
int a = 2;
namespace A1
{
    int a = 3;
}
namespace A2
{
    int a = 4;
}

int main()
{
    cout<<a<<endl;
    cout<<A1::a<<endl;
    cout<<A2::a<<endl;

    return 0;
}

运行结果像我们想的一样,就是2,3,4
这样就很好的避免了命名冲突的问题。

C++输入输出流

在C语言中输入输出是通过scanf和printf函数来实现的。
摁在C++中是通过调用输入输出流库中的流对象来实现的。
下面画图来说明一下。
这里写图片描述
输入输出流的基本操作

cout<<表达式1<<表达式2<<...endl;
cin>>变量1>>变量2>>...;

重载(C++为什么支持函数重载?)

什么是函数重载

函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。

#include<iostream>
 using namespace std;
 int Add(int *a,int *b)
 {
     return a+b;
 }
 double Add(double *a,double*b)
 {
     return a+b;
 }

C++为什么支持函数重载

那么C++为什么支持重载呢?那是因为C++有自己的一套函数名规则,你写的函数在你编译的时候名字就被编译器给改变了,他会根据函数的参数类型,个数重新命名。下面我们就来看一下它到底是怎么命名的。
这里写图片描述
由反汇编可以看出,实际上,编译器在处理的时候死吧她们当成两个不同的函数处理的,地址不同,所已在用的时候就可以找到他。
在c语言中,编译器在编译后在库中的名字为_Add,在c++中,编译器在编译后在库中的名字为_Add_int_int
函数的声明如下:int Add(float x,float y);在c语言中,编译器在编译后在库中的名字为_function在c++中,编译器在编译后在库中的名字为_Add_float_float,在找名字链接时,在C语言中两个的名字一样,就会在链接中报错,C++中名字不一样,不会报错。

构成重载的条件

  1. 函数名相同,在同一个作用域
  2. 参数不同(类型或者个数)
  3. 注意:返回值不同不能构成重载

C++缺省参数

什么是缺省参数

所谓缺省参数,顾名思义,就是在声明方法的某个参数的时候为之指定一个默认值,在调用该方法的时候如果采用该默认值,你就无须指定该参数。缺省参数使用主要规则:调用时你只能从最后一个参数开始进行省略,换句话说,如果你要省略一个参数,你必须省略它后面所有的参数。缺省参数的使用规则还包括:带缺省值的参数必须放在参数表的最后面。 缺省值必须是常量。显然,这限制了缺省参数的数据类型,例如动态数组和界面类型的缺省参数值只能是 nil;至于记录类型,则根本不能用作缺省参数。缺省参数必须通过值参或常参传递。

缺省的分类:
1. 全缺省:一个参数都不传,全用缺省参数。
2. 半缺省:一个缺省,一个不 缺省。
注意:缺省的参数必须是从右往左连续的,也就是说只能从右往左缺省不能跳着来。例如下

int Add(int a = 3,int b,int c = 5);//注意这样是不可以的。
//这要考虑函数建立栈桢,后进先出原则,传参的时候是从右往左。

指针和引用和const

什么是引用

引用的作用就是为变量起一个别名,也就是说有一个小名。

int a = 2;
int &b = a;//这里b就是a的引用 

这里还有知识点就是,const的引用。

const int a = 2;
const int &b = a;
//还有一个情况就是隐式类型转换
float b = 3.4;
int a = b;//这样编译时不会出现错误的,我们都知道是因为发生了隐式的类型转换。但是看下面这个,
int &b = a;//这样编译就会出错了,下面画图来说明为什么

这里写图片描述

引用的特点

  1. 一个变量可以有多个别名
  2. 引用必须初始化。
  3. 引用只能在初始化时引用一次,不能改变再去引用其他变量

引用的作用

  1. 作参数
int Add(int &a,int &b)
 {
     int ret = a + b;
     return ret;
 }
 double Add(double &a,double&b)
 {
     int ret = a + b;
     return ret;
 }

传引用可以不用再进行形参的实例化,提高效率,因为传了引用后就直接是实参的一个别名。一直真相比效率更高,因为指针还需要开辟4个字节来存地址。
2. 作返回值

int &Add(int &a,int &b)
 {
     int ret = a + b;
     return ret;
 }//这里作返回值就会减少内存的使用提高效率,因为用了引用,就不会再创建临时变量。
 但是在用的时候要注意,可能会出现问题。因为本来ret是临时变量,出了作用域后就不存在了,但是你给了它一个返回值为引用,就是内存泄漏了。这里是为了说明问题,说引用可以作返回值。

什么时候返回值用引用,什么时候不用引用。
注意:当那个变量出了作用域还存在,就可以用引用,当出了作用域就不存在了,就不要用引用。注意不要反悔临时变量的引用,会造成内存泄漏。
当那个临时变量很大时,就不要返回值,一般用再传一个参数来接收它,用这种方式解决。

引用和指针的区别和联系

  1. 引用只能在定义时初始化,之后不能指向其他(从一而终),而指针变量的值可以改变。
  2. 引用必须只想有效的变量,而指针可以为空
  3. sizeof 的使用,对引用来说,sizeof是指引用的变量的字节,而对指针而言,在32位平台下,是4个字节。
  4. 指针和引用的自增自减,引用是变量加1,指针是指向下一个位置。
  5. 相对额而言引用更加安全,当然,这只是相对的。指针更加的灵活,但是也更加危险。
  6. 程序为指针变量分配内存区域,而引用不分配内存区域
  7. 程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变指向的对象(指针变量中的值可以改),而引用对象不能改。
  8. 最后值得说的是,引用的底层实现就是用指针实现的。
原文地址:https://www.cnblogs.com/chan0311/p/9427339.html