接上节函数重载
1.名字修饰
在C语言中,名字修饰只是在函数名前加下划线,所以只要函数名相同,就会导致冲突。
在C++中,名字修饰是由“?函数名@域名1@域名2@...@参数列表@z”格式构成的,包含:
a. 函数名
b. 所在域
c. 参数列表
所以在C++中,以上三个必须完全相同,才会出现冲突,这就是函数重载的原理
2.extern "C"
使用extern "C"修饰一个语句或者将一段代码包起来,那么这条语句或者代码将会以C的风格进行编译。
/*#include <stdio.h>
extern "C"
{
int func(int a)
{
return a;
}
int func(int a, int b)
{
return a;
}
}
int main()
{
return 0;
}*/
一,引用
引用是给一个变量起别名,两个名字都是一个变量,所以操作谁结果上都一样。
引用是代替指针完成跨栈操作的,所以它具备指针跨栈的一切特点。
引用的底层实现实际是指针。
特点:
1,引用在定义时必须初始化(引用不存在空间,和变量共享,在底层实现实际是有空间的)
2,一个变量可以有多个引用
3,一个引用一旦引用了一个变量,就不能再引用其他变量了
使用场景:
1、做参数
a、输出型参数;b、提高效率
//引用做参数
void swap(int r1, int r2)
{
int tmp = r1;
r1 = r2;
r2 = tmp;
}
void swap_c(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void swap_cpp(int& r1, int& r2)
{
int tmp = r1;
r1 = r2;
r2 = tmp;
}
int main()
{
int a = 0, b = 1;
swap_c(&a, &b);
swap_cpp(a, b);
int x = 10;
int& y = x;
return 0;
}
2、做返回值
a、提高效率。
//引用做返回值
int Count1()
{
static int n = 0;
n++;
return n;
}
int& Count2()
{
static int n = 0;
n++;
return n;
}
int main()
{
const int& r1 = Count1();
int& r2 = Count2();
static int x = 0;
int& y = x;
return 0;
}
int Add1(int a, int b)
{
int c = a + b;
return c;
}
int main()
{
const int& ret = Add1(1, 2);
Add1(3, 4);
cout << "Add1(1, 2) is :" << ret << endl;
return 0;
}
int& Add2(int a, int b)
{
static int c = 1;
c = a + b;
return c;
}
int main()
{
int& ret = Add2(1, 2);
//Add2(3, 4);
printf("hello world\n");
cout << "Add2(1, 2) is :" << ret << endl;
return 0;
}
传值、传引用效率比较 :
以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低 。
#include <time.h>
struct A
{
int a[10000];
};
40000byte
A a;
值返回
A TestFunc1() { return a; }
引用返回
A& TestFunc2(){ return a;}
void main()
{
以值作为函数的返回值类型
size_t begin1 = clock();
for (size_t i = 0; i < 1000000; ++i)
TestFunc1();
size_t end1 = clock();
以引用作为函数的返回值类型
size_t begin2 = clock();
for (size_t i = 0; i < 1000000; ++i)
TestFunc2();
size_t end2 = clock();
计算两个函数运算完成之后的时间
cout << "TestFunc1 time:" << end1 - begin1 << endl;
cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
#include <time.h>
struct A{ int a[10000]; };
void TestFunc1(A a){}
void TestFunc2(A& a){}
void main()
{
A a;
// 以值作为函数参数
size_t begin1 = clock();
for (size_t i = 0; i < 100000; ++i)
TestFunc1(a);
size_t end1 = clock();
// 以引用作为函数参数
size_t begin2 = clock();
for (size_t i = 0; i < 100000; ++i)
TestFunc2(a);
size_t end2 = clock();
// 分别计算两个函数运行结束后的时间
cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
总结:
- 临时变量具有常性 --> const 。
- 参数、返回值传值会产生一个拷贝变量。
- 一个函数要使用引用返回,返回变量出了这个函数的作用域还存在,就可以使用引用返回,否则就不安全。
- 函数使用引用返回的好处:少创建拷贝一个临时对象,提高效率。
引用比指针安全(跨栈操作时),引用一般在传参和返回值的时候用
1,引用不能改指向
2,引用不能为空,不能野
3,引用操作引用就是操作变量,
int main()
{
const int a = 10;
const int &ra = a;
double b = 1.23;
const double &rb = b;
int ming = 5;
int &xiaoming = ming;
cout << &ming << endl;
cout << &xiaoming << endl;
cout << xiaoming << endl;*/
system("pause");
return 0;
}
二,内联函数
内联函数是调用时不创建新栈而直接在调用处展开的函数,关键字为inline。
内联函数是对编译器的一个建议,如果函数过于复杂,编译器会不接受你的建议,而处理成普通的函数。
Inline函数可以代替带参宏。
register是寄存器变量,不放在内存里。
inline int &func2(int &a)
{
return a;
}
inline int* func3(int *pa)
{
return pa;
}
int main()
{
int a = 3;
cout << (func2(a)=4) << endl;
*func3(&a) = 5;
system("pause");
return 0;
}
宏优点:
1.增强代码的复用性。 2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。(容易产生二意性,适合做简单的处理)
C++有哪些技术替代宏?
1. 常量定义 换用const
2. 函数定义 换用内联函
三,auto(C++11)
1. auto是一个类型修饰符,会根据你给变量初始化的值的类型来决定自己是什么类型
auto定义的变量必须初始化,否则不知道auto是什么类型
2. auto可以连续定义变量,类型由第一个定义的变量决定,后续不能违背这个类型,但是可以定义对应类型指的针和引用
auto不能作为函数的参数类型
auto不能参与数组的类型
C++11后, auto会失去原本的含义