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

C++总计63个关键字,C语言32个关键字
定义命名空间,我们用到一个新的关键字namespace,这个关键字后是命名空间的名字,然后用一个{},{}内的是命名空间的成员。
- // 关键字 名字
- namespace u1
- {
- int a; // 一个普通的int型变量
- // 也可以是一个函数
- int add(int a,int b)
- {
- return a + b;
- }
- }
- namespace u2
- {
- // 命名空间里面也可以嵌套命名空间
- namespace u3
- {
- int d1;
- int d2;
- }
- }
- // 如果说同一个工程下的不同文件,都有相同的命名空间,编译器最后会将其合并
-
- // test1.cpp
- namespace u4
- {
- int add(int a,int b)
- return a + b;
- }
-
- // test2.cpp
- namespace u4
- {
- int mul(int a,int b)
- return a * b;
- }
-
- // 最后这两个函数都是在u4这个命名空间下,不会冲突

注:命名空间其实相当于一个作用域,命名空间{}内的内容都是在这个空间里面,我们c++的标准库都在std这个命名空间下,如果想使用c++标准库的函数,容器,需要在前面加上用std这个命名空间
命名空间的使用方法有三种:
(1)
- // 1.命名空间名称及作用域限定符
- int main()
- {
- printf("%d\n",u1::a);
- return 0;
- }
(2)
- // 使用using将命名空间中成员引入
- using namespace u1::a; // 意思就是讲u1下的a变量展开,这时候它的作用域就是全局作用域
-
- int main()
- {
- printf("%d\n",a); // 这时候不用加命名空间和作用域限定符
- return 0;
- }
(3)
- using namespace u1; // 意思是将u1整个命名空间展开
-
- int main()
- {
- printf("%d\n",a);
- return 0;
- }
这是一个最简单的C++程序,里面包含了一个头文件iostream,一个main函数以及一句打印函数,我们看到在cout这个函数前面,加上了一个std::,这是因为iostream库是属于标准库的一块,在std这个命名空间下。
标准输入输出对象
标准库定义了4个IO对象,IO(输入输出),以下:
一个C++程序
(1)输出
- // 编写一个简单的c++程序
-
- #include <iostream> // C++标准库的iostream库,包含了c++的输入和输出函数
-
- int main()
- {
- // 打印hello world
- std::cout << "hello world" << std::endl;
- }
(2)输入
- #include <iostream>
-
- int main()
- {
- int a,b;
- std::cin >> a >> b; // 输入a和b
- std::cout << a << " " << b << std::endl;
- return 0;
- }
注:如果不想每次在cin或者cout前加上std::,可以使用前面讲的命名空间使用方法,很多人会使用using namespace std;,但是建议不要去这样做,因为c++标准库的内容都在std这个命名空间下,如果使用这句语句,会将标准库的内容暴露出来,那么像cout或者cin这些即常用又不像使用std::,可以使用以下方法。
- using namespace std::cout;
- using namespace std::cin;
缺省参数是声明或者定义一个函数,为参数指定一个默认值。
- #include <iostream>
- using namespace std::cout;
- using namespace std::cin;
-
- int fun(int a = 0)
- {
- return a;
- }
-
- int main()
- {
- cout << fun(); // 0
- cout << fun(1); // 1
- return 0;
- }
带默认值的参数,如果在传参时,没有传入指定参数,则该函数会使用这个缺省参数。
- // ... 头文件
-
- // 全缺省参数
- int add(int a = 0, int b = 1)
- {
- return a + b;
- }
-
- int main()
- {
- cout << add() << endl; // 结果为1
- cout << add(1, 2) << endl; // 结果为3
- cout << add(2) << endl; // 结果为3
- //add(, 1); 这个是错的,不能跳过第一个参数,传给第二个
- return 0;
- }

- // ... 头文件
-
- // 半缺省参数
- int add(int a, int b = 1)
- {
- return a + b;
- }
-
- int main()
- {
- cout << add() << endl; // 错误的,因为a没有默认参数
- cout << add(1, 2) << endl; // 结果为3
- cout << add(2) << endl; // 结果为3
- return 0;
- }
总结:
C++允许函数在统一作用域下出现同名函数,这些同名参数的参数个数或类型或顺序可以不同。
- int add(int a,int b)
- {
- return a + b;
- }
-
- int add(double a,double b)
- {
- return a + b;
- }
-
- int add(int a,int b,int c)
- {
- return a + b + c;
- }
-
- // 这里会发生函数重载失败
- double add(double a,double b)
- {
- return a + b;
- }

注:只有参数个数和类型还有顺序不同才可以发生重载,如果只是返回值不一样,编译器会认为是同一个函数。
引用的含义是给一个变量取一个别名,它是和引用的变量共享同一块空间。
- int main()
- {
- // 类型& 引用变量名 = 引用对象
- int a = 10;
- int& b = a; // b是a的别名
- cout << a << " " << b;
- return 0;
- }
结果都是10,但要注意一点,引用对象和别名的类型都要属于同一种类型。
- int main()
- {
- int a = 10;
- // int& ra; // 这条会报错
- int& ra = a;
- int& rra = a;
- int b = 20;
- ra = b; // 这句话不是修改引用对象,而是赋值
- return 0;
- }
- int main()
- {
- const int a = 10;
- // int& ra = a; // 这里会报错
- const int&ra = a;
-
- int b = 10;
- const int& rb = b; // 这里没问题
- }
结论:
在c语言中,如果想写一个交换函数,我们需要通过指针传地址,将其修改,在c++中,我们可以使用引用,引用本质上其实也是传地址的一种方式,但是引用更具有可读性。
- int swap(int &a,int &b)
- {
- int tmp = a;
- a = b;
- b = tmp;
- }
下面这段代码会输出什么,如果不加static会怎么样
- int& Count()
- {
- static int n = 0;
- n++;
- // ...
- return n;
- }
我们来看下非static的情况,这时的n是一个局部变量,我们知道局部变量出了函数作用域就会销毁,那这时候将一个局部变量进行引用返回,这个内存空间其实已经还给系统了。虽然第一次能够成功打印出结果,但是第二次是一个随机值。这不是我们想要的。
- int& Count()
- {
- int n = 0;
- n++;
- // ...
- return n;
- }

但如果是加上static的话,会是这个局部变量变为全局变量,全局变量的作用域是一直到整个程序结束。
C语言中,我们在进行传参的时候,会考虑使用两种传参方式,一种是传值,一种是传地址,其实c++的引用本质上就是传地址的方式。参考下面的代码,我们在传递一个数组的时候,如果采用传值的方式,会创建一个临时的拷贝,效率是非常低的,尤其是传入的参数特别大的时候。
- #include <time.h>
-
- struct A{ int a[10000]; };
- void TestFunc1(A a){}
- void TestFunc2(A& a){}
-
- void TestRefAndValue()
- {
- A a;
- // 以值作为函数参数
- size_t begin1 = clock();
- for (size_t i = 0; i < 10000; ++i)
- TestFunc1(a);
- size_t end1 = clock();
- // 以引用作为函数参数
- size_t begin2 = clock();
- for (size_t i = 0; i < 10000; ++i)
- TestFunc2(a);
- size_t end2 = clock();
- // 分别计算两个函数运行结束后的时间
- cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
- cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
- }

建议:尽可能使用const引用,我们前面知道进行引用传递的效率比传值效率高,但是,在有些场景下,我们并不想修改传入参数的值,这个时候可以使用const引用传址。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。