C++入门知识点

       今天我为大家带来的是有关C++入门知识点,总共分为5个小知识点,分别是:命名空间,缺省参数,函数重载,引用和auto关键字(C++11)。在这其中,我们还会穿插将一些知识点,希望大家可以认真观看。本次使用的变成语言为C++,编译器为vs2013。

命名空间

       在我们学习C语言时,应该写过几个项目吧,那些项目的文件很多,我们有时会不小心一个函数出现命名冲突或者出现之前定义过的变量,在后面的程序中重复修改而导致结果错误。为了防止这样的事发生,在C++中引入了命名空间的概念,使用命名空间的的目的,主要是为了对标识符的名称进行本地化,以避免命名冲突或者名字污染。

       命名空间定义:是用来限定名字的解析和使用范围的,它是C++开发大型程序的工具之一,其关键字为namespace,后面跟命名空间的名字。原理是将全局作用域划分为一个一个的命名空间,每个命名空间是一个独立的作用域,在不同命名空间内部定义的名字彼此之间互不影响,从而有效的避免了命名空间污染。​​​​

命名空间的定义

       下面我们来通过代码演示以下命名空间的使用方法。

//全局作用域下的定义
int a = 0;
//定义普通命名空间
namespace N1
{
//命名空间中既可以是函数,也可以是变量
int a = 1;//每个空间的变量都是独立的
int Add(int left, int right)
{
return left + right;
}
}
//命名空间还可以进行嵌套
namespace N2
{
int a = 0, b = 0;
namespace N3
{
int a = 0, b;
}
}
//在同一个工程中,可以存在相同名称的命名空间,最后会合并成一块命名空间
namespace N1
{
int Mul(int left, int right)
{
return left*right;
}
}

       上面的代码就是命名空间的创建方式和规则,我们也可以简单的画图说明。

C++入门知识点

      注意:一个命名空间不可以有相同的变量名称,但是一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。

命名空间的使用

       接下来我们用代码来看下命名空间到底如何使用。

namespace N1
{
int a = 1;
int Add(int left, int right)
{
return left + right;
}
}
int main()
{
cout << a<< endl;//不能直接使用,会出现报错,显示a未定义
return 0;
}

       下面我们来看三种正确使用命名空间的方法。

//使用命名空间名称+作用域限定符
namespace N1
{
int a = 10;
int b = 20;
int Add(int m, int n)
{
return m + n;
}
}
int main()
{
//命名名称+::,指定a是在N1中的变量
cout << N1::a << endl;//这里的cout为C++中的标准输出
return 0;
}
//使用using将命名空间中的成员引入
namespace N1
{
int a = 10;
int b = 20;
int Add(int m, int n)
{
return m + n;
}
}
using N1::a;//将命名空间中的a引入
int main()
{
cout << a << endl;//这时a输出的就是N1中的变量
return 0;
}
//使用using namespace命名空间名称引入
namespace N1
{
int a = 10;
int b = 20;
int Add(int m, int n)
{
return m + n;
}
}
using namespace N1;//将命名空间的整体引入到全局变量中
int main()
{
cout << a << endl;
return 0;
}

      注意:前两种方法较为繁琐,我们如果要使用命名空间中的成员,就需要大量写入命名空间+作用于限定符;第三种方法较为简洁,但是如果我们全局作用域中有相同的函数或变量,那么就会导致变量定义不明确。

缺省参数

       接下来是我们的缺省参数,本次主要讲解的是关于缺省参数的定义,使用方法和注意事项。

缺省参数的定义

      缺省参数:声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。

下来我们来介绍缺省参数的分类:全缺省参数和半缺省参数。

//全缺省参数
void Exchange(int a = 10, int b = 20)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}

当我们调用函数时,如果我们不传入数据,那么编译器就会使用我们给出的默认值;而当我们传入数据后,就会打印出给定的数据。

C++入门知识点

注意:传入数据,不能出现跨数据传入,否则会出现报错。

//半缺省参数
void Exchange(int a, int b,int c=30)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}

缺省参数注意事项

       这里我们需要注意,半缺省参数必须由右到左依次给出,并且中间不能有间隔。并且缺省参数不能在函数的声明和定义中同时出现,即如果我们声明中给出的缺省值和定义中给出的不一样就会出现定义不明确;其次,缺省值必须是常量或者全局变量

void Exchange(int a=10, int b, int c = 30)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
//会出现报错,缺少默认参数
void Add(int a = 10);
void Add(int a = 20)
{}
//会出现报错,默认参数重定义

函数重载

       函数重载算是我们本章的重点讲解内容了,在我们C++的学习中,我们对函数重载的理解非常重要,本次我们需要了解有关函数重载的概念,底层逻辑和使用方法。

函数重载的概念

       函数重载就好比我们汉字中的多音字,长,即念chang,又念zhang,看到的一样,但读出来却截然不同,具有不一样的读音,那么含义也就完全不一样。这样的思想也被运用到了编程语言中。

      函数重载:是指在同一个作用域内,有多个函数名相同,但是形参列表不同(参数类型不同,参数个数不同,参数顺序不同),返回值无关,我们将这种叫做重载函数。

       想要形成函数重载,需要满足以下条件:1.函数名相同,2.参数列表不同,3.在同一作用域内。下面我们来看几组用法成功的函数重载。

//函数原型
int Add(int m, int n)
{
return m + n;
}
double Add(double m, double n)//函数参数不同,返回值也不同
{
return m + n;
}
int Add(double m, int n)//函数参数不同,返回值相同
{
return m + n;
}

       以上函数,就可以看作是函数重载。都在全局作用域中,且每个函数的参数列表都不一样。但是,如果只有函数的返回值不同,参数列表相同,那么就不会构成函数重载。

C++修饰函数的底层逻辑

       那么接下来,我们想知道,为什么在C语言中,并没有函数重载,而只有C++中有呢。

       首先,我们要知道,在C/C++中,一个程序想要运行起来,需要经历四个步骤:预处理,编译,汇编和链接。下来我们就用画图的方式来为大家说明这几步在一个待运行程序中的作用。

C++入门知识点

对于我们已知的四大编译器功能,在这里也简单总结一下

C++入门知识点

接下来我们来看,C语言编译器对函数名称的修饰有什么规律呢??

int Add(int a, int b)
{
return a + b;
}
int main()
{
Add(1, 2);
return 0;
}

C++入门知识点

       我们在C语言的编译器下运行上述代码,在调试状态下,通过反汇编我们可以看到,对于C语言调用函数,生成可执行程序时,只是给函数名称前加了个_并没有别的区别函数的改动。

//下述代码为错误,只是为了展示C++对函数名称的改动
int Add(int a, int b);
int Add(double a, double b);
int main()
{
Add(1, 2);
Add(1.0,2.0);
return 0;
}

       尝试运行代码,我们发现,编译器给我们报错了。当我们细看报错内容时,会发现无法解析的外部符号,C++入门知识点C++入门知识点。这两个看起来很奇怪的名称就是C++编译器调用函数时修饰的名称。

C++入门知识点

       下面我们来看看这种名称的组成部分都是什么吧。

C++入门知识点

       上图就是C++编译器对于函数修饰的规则,这里只是介绍了基础部分,有兴趣的朋友可以继续深入学习。

引用

        接下来要讲解的知识,相当于指针的表兄弟,引用操作。对于引用,学习过C++的朋友应该都有了解,在很多代码练习题中都会出现C++入门知识点,我们可能不太了解加入&的作用,现在我们就来看看引用操作的定义和作用。

引用的定义

      引用:相当于一个变量的另一个名称,对引用的操作就是对变量的直接操作。引用保存着其对象的存储地址,编译器不会给引用变量开辟内存空间,它和引用变量共存一块内存空间。

        对于引用变量,这里我们介绍一种方法

//类型& 引用变量名称=引用实体
int main()
{
int a = 10;
int& b = a;//引用操作,引用类型和实体必须一致
cout << a << endl;
cout << b << endl;
}
//打印得到10和10

      注意:引用在定义时必须初始化一个变量可以有多个引用引用最多可以引用一个实体

int& Add(int m, int n)
{
int c = m + n;
return c;
}
int main()
{
int& ret = Add(1, 2);
cout << ret << endl;//3
Add(3, 4);
cout << ret << endl;//7
return 0;
}

       上述代码是对引用的常规操作,如果我们引用函数的返回值作为实体,那么在之后的程序运行中,只要函数的返回值发生改变,那么C++入门知识点的值也会发生改变。

引用的底层逻辑

接下来,我们来看看引用的底层逻辑吧

int main()
{
int a = 10;
int& b = a;
cout << "a的地址: " << &a << endl;//006FF80C
cout << "b的地址: " << &b << endl;//006FF80C
int *const c = &a;
return 0;
}

C++入门知识点

       通过上述代码的反汇编,我们可以看到引用C++入门知识点和指针C++入门知识点的汇编代码是一样的,因此引用的底层逻辑就是指针,并且由于引用无法改变指向对象,所以引用的指针为常指针

       虽然引用本身并没有内存,但实际上确实有内存的。当我们使用C++入门知识点运算引用常量时,会出现实体本身的大小,所以严格意义上,引用时具有内存大小的,只是不占用内存的真实大小。

最后,我们再来对比一下引用和指针的区别。

1.引用在定义时必须初始化,而指针没有明确要求。

2.引用初始化具有唯一性,而普通指针没有要求,可以随意更改指向对象。

3.没有空的引用,只用空的指针。

4.在C++入门知识点中含义不同:引用结果为引用类型大小,但指针始终是地址空间所占的字节(32位平台下占4个字节,64位平台下占8个字节)。

5.引用自加即引用实体加1,指针自加即指针向后偏移一个类型大小。

6.有多级指针,但没有多级引用。

7.访问方式不同:指针需要显示解引用,引用编译器自己处理

8.引用比指针使用起来更加稳定(指程序运行后)

auto关键字

       说实话,在我刷题的时候,我很少使用C++入门知识点关键字遍历,也很少使用C++入门知识点定义一个变量,但是C++入门知识点关键字在我们未来的开发软件中非常重要,尤其是在代码很长的项目中更是非常便利的函数类型。

auto的定义

在C++11中,标准委员会赋予了C++入门知识点全新的含义:

      C++入门知识点不再是一个存储类型的指示符,而是作为一个新的类型指示符来指示编译器,C++入门知识点声明的变量必须由编译器在编译时期推导而得。

我们来简单使用以下

int main()
{
int a = 10;
auto b = a;
cout << typeid(b).name() << endl;//打印出b的类型,int
return 0;
}

       注意:使用C++入门知识点定义变量时必须对其初始化,在编译器编译阶段,会根据初始化表达式推导C++入门知识点的实际类型。因此C++入门知识点并非一种“类型”的声明,而是一个类型声明时的“占位符”。

​auto使用说明

//auto在声明引用时,必须加&
int main()
{
int a = 10;
int& b = a;
auto c = b;//没有&操作符
//正确因改为auto& c=b,这样之后的修改c就可以接收到
a = 20;
cout << typeid(c).name() << endl;
cout << c << endl;//结果位10
return 0;
}
//在同一行定义多个变量时,变量类型必须一致
int main()
{
auto a = 10, b = 12.2;//编译失败,auto无法确定出售类型到底是哪个
return 0;
}

注意:C++入门知识点不能作为函数的参数,并且不能直接用来声明数组。

最后就是关于C++入门知识点非常便利的使用方法,范围C++入门知识点的使用。

int main()
{
int arr[10];
for (auto& e : arr)//for的循环迭代范围必须确定
{
cout << e << endl;//可以直接打印出arr的值
}
return 0;
}
发表评论

相关文章