命名空间
1 #include<iostream>
2 using namespace std;
3
4
5 int main() {
6
7 cout << "hello world" << endl;
8 return 0;
9 }
~
这里的 using namespace std;
是展开C++标准模板库,不展开我们需要指定
#include <iostream>
int main() {
std::cout << "hello world" << std::endl;
return 0;
}
这是指定的写法,C++的命名空间可以解决命名冲突的问题,所以练习的时候展开没有什么影响,项目的时候还是不建议的!
cout and endl用的比较平凡,但是我们又不想全部展开or指定
#include <iostream>
using std::cout;
using std::endl;
int main() {
cout << "hello world" << endl;
return 0;
}
单独指定命名空间的内容
命名空间的定义
#include <iostream>
2 #include <algorithm>
3 using namespace std;
4
5 namespace N {
6
7 void test() {
8 cout << "hello world" <<endl;
9 }
10
11 template<class T> //模板
12 void swap(T& a, T& b) {
13 cout << "void swap(T& a, T& b)" << endl;
14 T tmp = a;
15 a = b;
16 b = tmp;
17 }
18 }
19
20
21 void test() {
22 cout <<"hello C++" << endl;
23 }
24
25
26 int main() {
27
28 N::test();
29 test();
30 int a = 10;
31 int b = 11;
32 N::swap(a, b);
33
34 return 0;
35 }
hello world
hello C++
void swap(T& a, T& b)
这是执行结果,一个test是全局域,一个是我们定的命名空间域,可以有效的避免命名冲突
命名空间里可以嵌套命名空间,一个命名空间就定义了一个新的作用域
缺省参数
缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参
如果声明和定义分开,建议在声明给缺省参数
1 #include <iostream>
2 using namespace std;
3
4 //给了a缺省参数
5 void test(int a = 10) {
6 cout << a << endl;
7 }
8
9
10 int main() {
11
12 test();
13 return 0;
14 }
输出结果
[zt@VM-4-8-centos C++dir]$ ./a.out
10
缺省值必须是常量或者全局变量
缺省参数分类
- 全缺省参数
1 #include <iostream>
2 using namespace std;
3
4
5 void test(int a = 10, int b = 20, int c = 30) {
6 cout << a << endl;
7 cout << b << endl;
8 cout << c << endl;
9
10 }
11
12
13 int main() {
14
15 test();
16 return 0;
17 }
执行结果
[zt@VM-4-8-centos C++dir]$ ./a.out
10
20
30
有好多种使用方法这个比较简单我就不想列举了
2.半缺省参数
注意
- 半缺省参数必须从右往左依次来给出,不能间隔着给
- 缺省参数不能在函数声明和定义中同时出现
void TestFunc(int a, int b = 10, int c = 20)
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
int main() {
testFunc(1);
return 0;
}
[zt@VM-4-8-centos C++dir]$ ./a.out
a = 1
b = 10
c = 20
函数重载
概念:
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的
形参列表(参数个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题
C++可以函数重载的是函数名修饰规则带来的
推荐一篇大佬写的函数重载,非常棒:
吴秦大佬写的函数重载
引用
内联函数
概念:
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率
特性:
- inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的函数不适宜使用作为内联函数。
- inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等等,编译器优化时会忽略掉内联。
- inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到
auto
auto声明的变量必须由编译器在编译时期推导而得
在一些地方auto可以提高代码的阅读,一些迭代器写起来比较麻烦如:map/set, unordered_map/unordered_set写起来用auto就会非常爽
int main() {//std命名空间没有展开
std::unordered_map<std::string, std::string> un_map;
std::unordered_map<std::string, std::string>::iterator it = un_map.begin();
auto ait = un_map.begin();
return 0;
}
这个时候的auto就很舒服
注意:
使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型
auto的使用细则
- auto与指针和引用结合起来使用 用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
- 在同一行定义多个变量
当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量
void TestAuto()
{
auto a = 1, b = 2;
auto c = 3, d = 4.0; // 该行代码会编译失败,因为c和d的初始化表达式类型不同
}
auto不能推导的场景
1.auto不能作为函数的参数类型
2.auto不能直接声明数组
nullptr
NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码
在大多数情况下NUll和nullptr是一样的,但是在:
#include <iostream>
using namespace std;
void f(int* a) {
cout << "int*" << endl;
}
void f(int a) {
cout << "int" << endl;
}
int main() {
f(nullptr);
f(NULL);
return 0;
}
函数的重载会搞错