#include <iostream>
using namespace std;
相当于C的#include <stdio.h>
#include <iostream>
using namespace std;
namespace abc
{
int a = 1;
}
int a = 0;
int b = 2;
namespace oo
{
int a = 3;
}
int main()
{
int a = 4;
//使用命名区间abc中的a
cout << abc::a << endl;
//使用全局域的a
cout << ::a << endl;
//使用命名区间oo中的a
cout << oo::a << endl;
//使用当前函数内的a
cout<<a<<endl;
}
有的时候命名空间std中的内容不能全部展开可以这样
//使用命名区间abc中的a
std::cout << abc::a <<std:: endl;
//使用a
std::cout << a << std::endl;
//使用命名区间oo中的a
std::cout << oo::a << std::endl;
&取别名
为了避免函数调用的时候使用容易出错的指针,C++引入了引用(&)。
&引用不会再次开辟空间,与指针不同。
但在使用的时候还是要注意几点:
定义的时候就要赋值;接收返回值的时候要注意返回的是不是在函数里定义的临时变量;&的使用不能放大读写权限,即const 修饰的变量的别名也要有const修饰:const int& ;把double类型的变量强行放进int&时会创建一个临时变量,值是double的整数部分,临时变量具有常量的性质(常性),所以要用const int&来接受,否则编译不通过。
缺省参数
如果声明与定义分开,那么为了避免冲突,声明给缺省值,定义不给。
缺省值只允许从右往左给连续的缺省值,不可跳跃也不可中断。
函数重载原理(面试题:为什么C++支持函数重载而C语言不支持)
在C语言中不允许函数重名,但在C++中允许。
函数重载:函数名相同,函数的参数 类型/顺序/数量不同。返回值的类型不会影响函数重载
void Sweap(int& a, int& b)
{
int tmp = a;
a = b;
b = tmp;
}
void Sweap(double& a, double& b)
{
double tmp = a;
a = b;
b = tmp;
}
int main()
{
int a1 = 1, b1 = 2;
double a2 = 1.1, b2 = 2.2;
cout << a1 << " " << b1 << " -> ";
Sweap(a1, b1);
cout << a1 << " " << b1 << endl;
cout << a2 << " " << b2 << " -> ";
Sweap(a2, b2);
cout << a2 << " " << b2 << endl;
}
要理解函数重载有两步:1.编译链接的过程;2.C++和C在编译链接中的区别。
1.编译链接的过程
编译链接的过程有4步:预处理,编译,汇编,链接
从上面的图可以看出f 和 test在链接之前都是单线的互不干扰,只有在链接的时候才汇合到一起。
在汇编的时候会产生一个符号表专门存放函数名称和函数的地址。
在编译中产生的汇编代码时在生成函数的汇编码时找到了对函数的声明(预处理中展开了头文件),但是找不到具体的地址所以会生成一个随机的地址。在链接的时候与符号表中的函数名一一比对填上函数地址。
2.C++和C的在编译链接中的区别
主要体现在符号表的生成上,C++在生成符号表的时候不仅有函数名还对函数名做了修饰如图:
linux下C++的命名规则:_Z+长度+函数名+类型首字母而C则没有对函数名的修饰。
inline
实现ADD的宏:
#define ADD(int x,int y) ((x)+(y))
宏的写法不容易控制所以就有了inline
inline函数的声明和定义要放在一起:
在预编译的时候把inline类型的函数全部转换成代码。适用于代码行小于10行的函数
在类的声明中,当头文件和代码实现分开的时候,在头文件中实现的代码会变成inline类型 。
auto
auto可以自动识别类型
int a = 10;
//auto一定在定义的时候就赋值,不能出现:auto d;这种写法
auto* pa = &a;
auto b = a;
//注意这个是引用
auto& c = a;
const int aa = 20;
auto& bb = aa;
//typideid是获取这个变量的类型
cout << typeid(pa).name() << endl;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(bb).name() << endl;
主要有两个用途,一是替代类型特别长的类型,让编译器自己识别还有就是用于范围for
范围for
int arr[] = { 1,2,3,4,5,6,7,8,9 };
for (auto e : arr)
cout << e << " ";
cout << endl;
//修改数组中的元素要取别名
for (auto& e : arr)
e *= 2;
for (auto e : arr)
cout << e << " ";
cout << endl;
但是auto不能做函数的参数,不能做返回值,不可以在一行定义类型不同的多个变量。
而且下面的的范围for是不允许的:
void f(int arr[])
{
for (auto e : arr)
cout << e << endl;
}
这是因为在传数组的时候传的是地址,范围for无法根据一个地址遍历数组。