一.命名空间
在C/C++中,变量、函数和类都是大量存在的,这些变量、函数和类的名称都将作用于全局作用域中,可能会导致很多冲突,所以我们就选择使用命名空间。
命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或者名字污染。
1.定义:
定义一个命名空间,需要用到namespace关键字,后跟命名空间。
namespace n1//普通的命名空间
{
int a = 10;//定义变量
int b = 20;
int add(int left, int right)//定义函数
{
return left + right;
}
}
namespace n2
{
int c = 30;
int sub(int left, int right)
{
return left - right;
}
namespace n3//命名空间可以嵌套
{
int mul(int left, int right)
{
return left*right;
}
}
}
namespace n1//同一个工程中允许多个相同名称的命名空间,编译器会将多个合成一个命名空间
{
int c = 50;
}
2.使用(三种方式)
(1)使用作用域限定符
int main()
{
printf("%d\n",n1::a );
system("pause");
return 0;
}
(2)使用using将命名空间中的成员引入
using n1::b;
int main()
{
printf("%d\n", b);
system("pause");
return 0;
}
(3)使用using namespace命名空间名称引入
using namespace n1;
int main()
{
printf("%d\n", add(10, 20));
system("pause");
return 0;
}
二.缺省参数
1.概念
缺省参数是声明或者定义函数时对函数的参数指定一个默认值。在调用函数时,如果没有指定实参则采用默认值,否则使用指定的实参。
void test(int a = 100)
{
cout << a << endl;
}
int main()
{
test();//无参
test(10);//有参
system("pause");
return 0;
}
2.分类
(1)全缺省参数
(2)半缺省参数
void test(int a = 100, int b = 10, int c = 1)//全缺省参数
{
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "c=" << c << endl;
}
void test(int a, int b = 10, int c = 1)//半缺省参数
{
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "c=" << c << endl;
}
3.特点
(1)半缺省参数必须从右到左依次给出,不能间隔。
(2)缺省参数不能同时在函数声明和定义中出现。
(3)缺省值必须是常量或者全局变量
(4)C语言不支持
三.函数重载
1.函数重载是函数的一种特殊情况,C++允许在同一个作用域中声明几个功能类似的同名函数,这些同名函数的形参必须不同。常用于处理功能类似但是类型不同的问题。
int add(int a, int b)
{
return a + b;
}
double add(double a, double b)
{
return a + b;
}
long add(long a, long b)
{
return a + b;
}
short add(short a, short b)
{
return a + b;
}
int main()
{
int ret1 = add(1, 2);
double ret2 = add(1.0, 2.0);
long ret3 = add(1L, 2L);
short ret4 = add(1, 2);
system("pause");
return 0;
}
extern"C"在C++工程中将某个函数按照C的风格来编译。
四.引用
1.概念
引用不是定义一个变量,而是给已存在的变量去一个别名, 编译器不会为引用变量开辟内存空间,它和它的引用空间公用一块内存空间。
void test()//引用类型必须和引用实体是同类型的
{
int a = 10;
int & ra = a;
printf("%p\n", &a);
}
2. 特性
(1)引用在定义时必须初始化
(2)一个变量可以有多个引用
(3) 引用一旦引用了一个实体,再不能引用其他实体
void test1()//引用类型必须和引用实体是同类型的
{
int a = 10;
//int &ra;//这条语句会出错
int & ra = a;
int& rra = a;
printf("%p\n", &a);
printf("%p\n", &ra);
printf("%p\n", &rra);
}
3. 常引用
void test()
{
const int a = 10;
//int & ra = a; //出错
const int& rra = a;
double b = 20.0;
//int& rb = b; //出错
const double&rrb = b;
}
4.使用场景
(1)作参数
void swap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
(2)作返回值
int& testret(int&a)
{
a = a + 10;
return a;
}
5.传值、传地址、传引用效率比较
struct A
{
int arr[10000];
int size;
};
void testref(A& param)
{
}
void test()
{
A a;
size_t begin = GetTickCount();//从开机到现在的时间
for (size_t i = 0; i < 1000000; i++)
testref(a);//传指针 16 传引用 15
size_t end = GetTickCount();
cout << end - begin << endl;
}
通过比较,我们发现引用和指针在传参的效果几乎相同
6.引用和指针的区别
(1)引用自在定义时必须初始化,指针没有要求;
(2)引用在初始化时引用一个实体后,就不能在引用其他实体,而指针可以在任何时候指向一个同类型实体;
(3)没有NULL引用,有NULL指针;
(4)在sizeof中含义不同,引用的结果为引用类型的大小;指针永远就是地址所占的字节数;
(5)引用自加一即是引用实体增加一,指针自加一即是指针向后偏移一个类型的大小;
(6)有多级指针,但是没有多级引用;
(7)访问实体类型不同;指针需要显示解引用,引用编译器自己处理
(8)引用比指针使用起来相对更安全
五.内联函数
1.概念
以inline修饰的函数叫作内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行效率。
int add(int x, int y)
{
return x + y;
}
int main()
{
int ret = 0;
ret = add(10, 20);
cout << ret << endl;
system("pause");
return 0;
}
在release下,汇编代码中没有call;
在debug下,先对编译器修改;如下:项目-->xxx.cpp属性-->配置(Debug)
没有call指令
2.特性
(1)inline是一种以空间换取时间的做法,省去调用函数的开销,所以代码很长或者有循环/递归的函数不适合使用内联函数。
(2)inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数中有循环/递归等等,编译器会在优化时忽略掉内联函数。