1.重载:
C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。函数重载要求参数不同!而跟返回值没关系。
2.缺省参数:
声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该
默认值,否则使用指定的实参。半缺省参数必须从右往左依次来给出,不能间隔着给(就是只能前面的形参没有默认值,有默认值的在后面),缺省参数不能在函数声明和定义中同时出现.
3.命名空间:
一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中.
同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中,命名空间可以嵌套
命名空间有三种使用方式:
namespace N1
{
int a=0;
int Add(int left, int right)
{
return left + right;
}
}
namespace N2
{
int a=2;
int b=3;
int Add(int left, int right)
{
return left + right;
}
}
using N2::b
using namespce N1;
int main()
{
printf("%d\n", N1::a);//1.每次使用该命名空间里的内容就:命名空间名+::(作用域限定符)
printf("%d\n", b);//2.使用 using+命名空间名::成员 引入
Add(10, 20);//使用 using namespace + 命名空间名称 引入整个命名空间,所以会调用N1里的add函数
return 0;
}
第三种方法,直接引入整个命名空间,使代码体积变大换来便利
4.引用:
void TestConstRef()
{
const int a = 10;//const关键字,a定义为常量
int& ra = a; // 错,a为常量
const int& ra = a;//对
int& b = 10; // 错,b为常量
const int& b = 10;//对,b也是常量了
double d = 12.34;
int& rd = d; // 错,类型不同
const int& rd = d;//对,rd会引用一个无名临时空间变量,是转为int类型的
//引用了某实体后不能再引用其他实体
}
/*const是用来定义一个常量 const int* p=&a后可以使p=&b,不能写*p=100(非1的数都不行,int a=1)int* const p=&a则反之,两个情况结合则都不能修改
若a是个常量:const a=10,只能用const int* p=a或者const int* const p=a来接收a地址,因为int* const p=a是可以通过解引用修改a的值,而a是个常量不能被修改*/
引用就是一个变量的别称,不创建另外的独立空间,就是同一内存空间有两个(多个)变量名,操作哪个变量名都是操作同一内存空间里的内容,可以在形参时用也可以做函数返回值时用:
void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
//交换两个数据时不需要传指针创建形参变量,
//传引用直接操作,效率高的多,引用做返回值时同理
但是!在底层实现上实际是有空间的,因为引用是按照指针方式来实现的
比如int a=10; int* p=&a; int* &rp=p;指针的引用,
int a[]={1,2,3,4,5,6}; int(&ra)[]=a;数组的引用
5.内联函数:
在函数定义时返回值前加个inline,是一种以空间换时间的做法,省去调用函数额开销。
inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等较复杂时,编译器优化时会忽略掉内联。就是在函数简单又频繁时使用内联相当于,直接将被调用的函数代码写在调用处,省下了调用函数的时间
inline不能声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到(即声明和定义在不同文件里)
【面试题】
宏的优缺点?
优点:
1.增强代码的复用性。
2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。
C++有哪些技术替代宏?
1. 常量定义 换用const
2. 函数定义 换用内联函数
6.auto关键字:
自动推导类型用,auto不能直接用来声明数组,也不能用来做形参类型
int main()
{
int x = 10;
auto a = &x;
auto* b = &x;
auto& c = x;
cout << typeid(a).name() << endl;//int*
cout << typeid(b).name() << endl;//int*,做指针时auto和auto*无区别
cout << typeid(c).name() << endl;//int
//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
return 0;
}
7.nullptr
c++11中使用了nullptr,因为c98的NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
可以看到,NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,比如:
void f(int)
{
cout<<"f(int)"<<endl;
}
void f(int*)
{
cout<<"f(int*)"<<endl;
}
int main()
{
f(0);//f(int)
f(NULL);//f(int),而使用nullptr则不会出现此问题
f((int*)NULL);//f(int*)
return 0;
}