当前位置:   article > 正文

C++入门篇——基本语法详解_c++语法

c++语法

C是C++的子集,在C语言的基础上添加了面向对象的特性,以及C++标准库。

1. C++关键字

 C++总计63个关键字,C语言32个关键字

2. 命名空间

2.1 命名空间的语法

 定义命名空间,我们用到一个新的关键字namespace,这个关键字后是命名空间的名字,然后用一个{},{}内的是命名空间的成员。
 

  1. // 关键字 名字
  2. namespace u1
  3. {
  4. int a; // 一个普通的int型变量
  5. // 也可以是一个函数
  6. int add(int a,int b)
  7. {
  8. return a + b;
  9. }
  10. }
  1. namespace u2
  2. {
  3. // 命名空间里面也可以嵌套命名空间
  4. namespace u3
  5. {
  6. int d1;
  7. int d2;
  8. }
  9. }
  1. // 如果说同一个工程下的不同文件,都有相同的命名空间,编译器最后会将其合并
  2. // test1.cpp
  3. namespace u4
  4. {
  5. int add(int a,int b)
  6. return a + b;
  7. }
  8. // test2.cpp
  9. namespace u4
  10. {
  11. int mul(int a,int b)
  12. return a * b;
  13. }
  14. // 最后这两个函数都是在u4这个命名空间下,不会冲突

注:命名空间其实相当于一个作用域,命名空间{}内的内容都是在这个空间里面,我们c++的标准库都在std这个命名空间下,如果想使用c++标准库的函数,容器,需要在前面加上用std这个命名空间

 2.2 命名空间的用法

命名空间的使用方法有三种:

(1)

  1. // 1.命名空间名称及作用域限定符
  2. int main()
  3. {
  4. printf("%d\n",u1::a);
  5. return 0;
  6. }

(2) 

  1. // 使用using将命名空间中成员引入
  2. using namespace u1::a; // 意思就是讲u1下的a变量展开,这时候它的作用域就是全局作用域
  3. int main()
  4. {
  5. printf("%d\n",a); // 这时候不用加命名空间和作用域限定符
  6. return 0;
  7. }

(3)

  1. using namespace u1; // 意思是将u1整个命名空间展开
  2. int main()
  3. {
  4. printf("%d\n",a);
  5. return 0;
  6. }

3. C++的输入和输出

这是一个最简单的C++程序,里面包含了一个头文件iostream,一个main函数以及一句打印函数,我们看到在cout这个函数前面,加上了一个std::,这是因为iostream库是属于标准库的一块,在std这个命名空间下。

标准输入输出对象 

标准库定义了4个IO对象,IO(输入输出),以下:

  1. cin是一个istream流对象,现在理解为标准输入即可。
  2. cout是一个ostream流对象,理解为标准输出即可。
  3. cerr是用来输出警告和错误信息的,所以也成为标准错误
  4. clog是用来输出程序运行的一般信息。

 一个C++程序

(1)输出

  1. // 编写一个简单的c++程序
  2. #include <iostream> // C++标准库的iostream库,包含了c++的输入和输出函数
  3. int main()
  4. {
  5. // 打印hello world
  6. std::cout << "hello world" << std::endl;
  7. }

(2)输入

  1. #include <iostream>
  2. int main()
  3. {
  4. int a,b;
  5. std::cin >> a >> b; // 输入a和b
  6. std::cout << a << " " << b << std::endl;
  7. return 0;
  8. }

 注:如果不想每次在cin或者cout前加上std::,可以使用前面讲的命名空间使用方法,很多人会使用using namespace std;,但是建议不要去这样做,因为c++标准库的内容都在std这个命名空间下,如果使用这句语句,会将标准库的内容暴露出来,那么像cout或者cin这些即常用又不像使用std::,可以使用以下方法。

  1. using namespace std::cout;
  2. using namespace std::cin;

 4. 缺省参数

4.1 缺省参数的定义和使用

 缺省参数是声明或者定义一个函数,为参数指定一个默认值

  1. #include <iostream>
  2. using namespace std::cout;
  3. using namespace std::cin;
  4. int fun(int a = 0)
  5. {
  6. return a;
  7. }
  8. int main()
  9. {
  10. cout << fun(); // 0
  11. cout << fun(1); // 1
  12. return 0;
  13. }

带默认值的参数,如果在传参时,没有传入指定参数,则该函数会使用这个缺省参数。 

4.2 缺省参数的分类 

  •  全缺省参数 
  •  半缺省参数
  1. // ... 头文件
  2. // 全缺省参数
  3. int add(int a = 0, int b = 1)
  4. {
  5. return a + b;
  6. }
  7. int main()
  8. {
  9. cout << add() << endl; // 结果为1
  10. cout << add(1, 2) << endl; // 结果为3
  11. cout << add(2) << endl; // 结果为3
  12. //add(, 1); 这个是错的,不能跳过第一个参数,传给第二个
  13. return 0;
  14. }
  1. // ... 头文件
  2. // 半缺省参数
  3. int add(int a, int b = 1)
  4. {
  5. return a + b;
  6. }
  7. int main()
  8. {
  9. cout << add() << endl; // 错误的,因为a没有默认参数
  10. cout << add(1, 2) << endl; // 结果为3
  11. cout << add(2) << endl; // 结果为3
  12. return 0;
  13. }

总结

  1. 面对带默认参数的函数,在全缺省的情况下,可以不传入参数就进行调用,如果只传入一部分参数,那么这些参数默认从前面开始一一传入。但是要注意一点,不可以跳过前面的参数进行传入。
  2. 在半缺省的情况下,半缺省并不是指缺省一半的意思,是指有至少一个缺省,却不是全缺省。半缺省指定默认参数的时候,如果一个变量设置了默认参数,那么它后面的参数都要设置默认参数。

5. 函数重载 

C++允许函数在统一作用域下出现同名函数,这些同名参数的参数个数或类型或顺序可以不同。

  1. int add(int a,int b)
  2. {
  3. return a + b;
  4. }
  5. int add(double a,double b)
  6. {
  7. return a + b;
  8. }
  9. int add(int a,int b,int c)
  10. {
  11. return a + b + c;
  12. }
  13. // 这里会发生函数重载失败
  14. double add(double a,double b)
  15. {
  16. return a + b;
  17. }

注:只有参数个数和类型还有顺序不同才可以发生重载,如果只是返回值不一样,编译器会认为是同一个函数。

6. 引用

6.1 引用概念

 引用的含义是给一个变量取一个别名,它是和引用的变量共享同一块空间。

  1. int main()
  2. {
  3. // 类型& 引用变量名 = 引用对象
  4. int a = 10;
  5. int& b = a; // b是a的别名
  6. cout << a << " " << b;
  7. return 0;
  8. }

结果都是10,但要注意一点,引用对象和别名的类型都要属于同一种类型。

6.2 引用特性

  1. 引用必须在开始初始化
  2. 一个变量可以有多个引用
  3. 引用一旦初始化后,就不可以再引用其他变量
  1. int main()
  2. {
  3. int a = 10;
  4. // int& ra; // 这条会报错
  5. int& ra = a;
  6. int& rra = a;
  7. int b = 20;
  8. ra = b; // 这句话不是修改引用对象,而是赋值
  9. return 0;
  10. }

 6.3 常引用

  1. int main()
  2. {
  3. const int a = 10;
  4. // int& ra = a; // 这里会报错
  5. const int&ra = a;
  6. int b = 10;
  7. const int& rb = b; // 这里没问题
  8. }

结论:

  1. 无法使用非const的引用对常量进行引用
  2. 可以对变量进行const引用,那么这个const引用的属性为只读 

6.4 使用场景

 在c语言中,如果想写一个交换函数,我们需要通过指针传地址,将其修改,在c++中,我们可以使用引用,引用本质上其实也是传地址的一种方式,但是引用更具有可读性。

  1. int swap(int &a,int &b)
  2. {
  3. int tmp = a;
  4. a = b;
  5. b = tmp;
  6. }

 下面这段代码会输出什么,如果不加static会怎么样

  1. int& Count()
  2. {
  3. static int n = 0;
  4. n++;
  5. // ...
  6. return n;
  7. }

我们来看下非static的情况,这时的n是一个局部变量,我们知道局部变量出了函数作用域就会销毁,那这时候将一个局部变量进行引用返回,这个内存空间其实已经还给系统了。虽然第一次能够成功打印出结果,但是第二次是一个随机值。这不是我们想要的。 

  1. int& Count()
  2. {
  3. int n = 0;
  4. n++;
  5. // ...
  6. return n;
  7. }

但如果是加上static的话,会是这个局部变量变为全局变量,全局变量的作用域是一直到整个程序结束。 

6.5 传值和传址效率对比

C语言中,我们在进行传参的时候,会考虑使用两种传参方式,一种是传值,一种是传地址,其实c++的引用本质上就是传地址的方式。参考下面的代码,我们在传递一个数组的时候,如果采用传值的方式,会创建一个临时的拷贝,效率是非常低的,尤其是传入的参数特别大的时候。

  1. #include <time.h>
  2. struct A{ int a[10000]; };
  3. void TestFunc1(A a){}
  4. void TestFunc2(A& a){}
  5. void TestRefAndValue()
  6. {
  7. A a;
  8. // 以值作为函数参数
  9. size_t begin1 = clock();
  10. for (size_t i = 0; i < 10000; ++i)
  11. TestFunc1(a);
  12. size_t end1 = clock();
  13. // 以引用作为函数参数
  14. size_t begin2 = clock();
  15. for (size_t i = 0; i < 10000; ++i)
  16. TestFunc2(a);
  17. size_t end2 = clock();
  18. // 分别计算两个函数运行结束后的时间
  19. cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
  20. cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
  21. }

建议:尽可能使用const引用,我们前面知道进行引用传递的效率比传值效率高,但是,在有些场景下,我们并不想修改传入参数的值,这个时候可以使用const引用传址。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/42225
推荐阅读
相关标签
  

闽ICP备14008679号