三、内联函数inline
1、普通函数
普通函数会被编译成二进制指令存储在代码段中,调用语句会生成一条跳转指令,当程序运行到调用语句时,会跳转该函数在代码段中对应的位置执行,执行结束会返回
2、什么是内联函数
内联函数也会被翻译成二进制指令,但调用语句不会生成跳转指令,而是直接把内联函数的二进制指令进行替换,就没有跳转和返回,而是直接执行二进制指令,这种函数称为内联函数
3、显式内联和隐式内联
显式内联:
在函数的返回值前加 inline 该函数就以内联函数的机制调用
隐式内联:
在结构、联合、类中的成员函数会自动被当做内联函数处理
注意:如果在结构、联合、类中声明成员函数,但是在外面定义,则不会当做内联函数处理
实例:
#include <iostream>
using namespace std;
inline void func(void)
{
cout << "我是显示内联" << endl;
}
struct Data
{
void func(void)
{
}
void func1(void);
};
void Data::func1(void);
{
}
int main(int argc,const char* argv[])
{
for(int i=0; i<10000000; i++)
{// 适合内联
func();
}
}
注意:
-
函数是否被内联由编译器以及它的优化等级决定,加 inline 只是有可能影响它的决定
-
g++默认优化等级 -O -O1 下所有的内联函数都会当成普通函数处理
在-O2 -O3的优化级别下,甚至普通函数都可能会被当做内联函数处理
- c99 也支持 inline
4、内联的适用条件
-
优点:节约了函数传参、跳转、返回的时间,提高代码的运行速度
-
缺点:当被多个位置调用时,那么二进制指令会被拷贝多份,产生了冗余,导致可执行文件明显增加
-
适用条件:
①、适合内容简单且同一位置频繁调用的函数
②、不适合内容多、且多个位置、较少调用的函数,因为节约的时间还弥补不过牺牲的空间
③、带有递归属性的函数无法内联,编译器会自动忽略
5、内联函数和宏函数的比较
-
相同点:都是采用以空间换时间的策略提高程序的运行速度,减少函数调用跳转的耗时
-
不相同:
①、宏函数不是真正的函数,只是语句替换,不会对参数进行类型检查、没有返回值、安全性低
②、内联函数是真正的函数、严格检查参数类型、有返回值、安全性高
四、引用
引用就是一种取别名的机制
格式:
类型名& 别名 = 数据;
实例:
#include <iostream>
using namespace std;
void func(int& num)
{
num++;
cout << num << " " << &num << endl;
}
int main(int argc,const char* argv[])
{
int num = 10;
int& hehe = num; // 给num取别名hehe
// int& xixi;
hehe = 88;
cout << num << endl;
cout << &hehe << " " << &num << endl; //地址相同
func(num);
cout << num << endl;
}
输出:
88
0xbfd67ce8 0xbfd67ce8
89 0xbfd67ce8
89
为什么要使用指针:
1、跨函数共享变量(输出型参数),引用可替代
2、提高传参效率,引用可替代,效率比指针还高,不拷贝字节
3、配合堆内存使用,只能使用指针
4、配合字符串使用,string类可以替代
什么情况下使用引用:
1、跨函数共享变量,引用比指针更安全(无需直接操作地址空间、不存在空引用,也极少出现野引用问题)、也比指针更方便(无需缺地址、解引用)
2、提高传参效率,引用的效率比指针还高,指针最起码还要传递4/8字节的地址编号,但是引用一个字节都不需要传递,但是引用和指针一样都有被修改的风险,因此为了保护目标需要增加const
使用引用需要注意的问题:
1、引用必须初始化,所以不存在空的引用,一个变量可以有多个引用
2、可以引用右值(不能进行取地址),但是必须使用const修饰引用
右值(不能进行取地址):一个表示数据的表达式(如字面常量、函数的返回值、表达式的返回值)
3、引用不能中途更改引用的目标
4、函数的返回值类型可以是引用类型,但不能返回局部变量的引用
int a = 10;
//int& hehe; 编译时会报错
int& hehe = a;
int& xixi = a;
指针与引用的比较(常考面试题)
相同点
1、都可以跨函数共享内存,都可以提高函数传参效率、也需要const保护
2、可以定义数组指针,也可以定义数组引用
int arr[5] = {1,2,3,4,5};
int (*arrp)[5] = &arr;
int (&hehe)[5] = arr;
3、可以定义函数指针,可以定义函数引用
void (*fp)(void) = func;
fp();
void (&xixi)(void) = func;
xixi();
实例:
#include <iostream>
using namespace std;
void func(void)
{
cout << "func" << endl;
}
int main(int argc,const char* argv[])
{
/*
int* arr[5];
int num = 0;
int& arr1[1] ={num} ;
*/
int arr[5] = {1,2,3,4,5};
int (*arrp)[5] = &arr;
int (&hehe)[5] = arr;
for(int i=0; i<5; i++)
{
cout << arr[i] << " " << hehe[i] << endl;
}
void (*fp)(void) = func;
fp();
void (&xixi)(void) = func;
xixi();
}
输出:
1 1
2 2
3 3
4 4
5 5
func
func
不同点
1、引用是一种取别名的机制,指针是一种数据类型
2、引用不需要额外存储空间,指针需要4/8字节用于存储内存地址
3、指针可以不初始化,引用必须初始化
4、指针有空指针,但没有空引用
5、指针可以更改指向的目标,但引用不可以
6、指针可以配合堆内存使用,而引用不行
7、可以定义指针数组,但不能定义引用数组
五、C++的强制类型转换
C语言原来的强制类型转换依然可以在C++中继续使用
(新类型)数据
注意:强制类型转换都只是得到一个临时结果,数据原来的类型不会改变
- 为什么C++要重新设计强制类型转换?
因为C语言的强制类型转换虽然自由度高,但是非常危险
- 为什么C++之父设计强制类型转换设计得很复杂、使用很麻烦?
因为他认为只有在程序设计不合理的情况下才需要强制类型转换,之所以设计复杂就是不想让程序员使用,而是去反思、重新设计自己的代码
1、静态类型转换
目标类型和原数据类型之间必须有一个方向能够自动类型转换,否则出错
static_cast<目标类型>(原数据)
实例:
#include <iostream>
using namespace std;
int main(int argc,const char* argv[])
{
int num = 65;
cout << static_cast<char>(num) << endl; //输出A
void* p = NULL;
static_cast<int*>(p);
//static_cast<int>(p); //编译器报错
}
2、动态类型转换
目标类型和原数据类型之间必须存在继承关系,并且目标类型必须是指针类型或引用类型,否则出现错误
dynamic_cast<目标类型>(原数据)
实例:
#include <iostream>
using namespace std;
struct Man
{
};
struct Student : public Man
{
};
int main(int argc,const char* argv[])
{
Student s;
dynamic_cast<Man&>(s);
}
3、去常类型转换
目标类型必须是指针或引用,且除了const属性不同,其它都要相同,否则出现报错
const_cast<目标类型>(原数据)
实例:
#include <iostream>
using namespace std;
int main(int argc,const char* argv[])
{
const int num = 65;
cout << const_cast<int&>(num) << endl;
int* p = const_cast<int*>(&num);
//int* p1 = # 无法转换
}
4、重解释类型转换
只能把整数转成指针,或者把指针转成整数,否则会出错
reinterpret_cast<目标类型>(原数据)
实例:
#include <iostream>
using namespace std;
int main(int argc,const char* argv[])
{
int num = 65;
cout << reinterpret_cast<short*>(num) << endl; //输出0x41
cout << reinterpret_cast<unsigned long>(&num) << endl; //输出3212993788
}
标签:类型转换,函数,int,C++,引用,内联,指针
From: https://www.cnblogs.com/ljf-0804/p/17652976.html