引用,内联函数,auto

接上节函数重载

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;
}

总结:

  1. 临时变量具有常性 --> const 。
  2. 参数、返回值传值会产生一个拷贝变量。
  3. 一个函数要使用引用返回,返回变量出了这个函数的作用域还存在,就可以使用引用返回,否则就不安全。
  4. 函数使用引用返回的好处:少创建拷贝一个临时对象,提高效率。

引用比指针安全(跨栈操作时),引用一般在传参和返回值的时候用

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会失去原本的含义

 

 

 

 

 

 

 

<think>嗯,用户现在想了解内联函数的概念、作用、优势和使用场景。根据之前提供的引用内容,我需要整理出相关的信息,并且结合之前的回答模式来组织内容。首先,内联函数的作用主要是减少函数调用的开销,通过将函数体直接插入调用处来避免栈帧创建和跳转。优势包括性能提升,尤其是对于频繁调用的小函数,同时还能提供类型安全检查,相比宏更安全。使用场景的话,引用里提到适合短小且频繁调用的函数,比如简单的getter/setter或者小型数学运算。 接下来需要考虑用户可能的深层需求。用户可能想知道什么时候不应该使用内联函数,比如对于大函数、递归函数或者包含循环的情况,这些情况下内联反而可能导致代码膨胀,降低性能。此外,用户可能还想知道如何正确使用inline关键字,以及编译器如何处理内联请求,比如是否一定会内联,或者只是建议。 需要确保回答结构清晰,分点说明,并给出代码示例,这样用户更容易理解。还要注意引用来源,比如提到内联函数和宏的区别时引用[2],或者提到使用场景的限制时引用[3]。同时,要避免技术错误,比如明确内联函数在编译时展开,而不是预处理阶段,这点和宏不同。此外,可能需要提到现代编译器的自动优化能力,即使没有inline关键字,编译器也可能自动内联小函数,而使用inline更多是给编译器的建议。 最后,生成的相关问题需要围绕内联函数的扩展内容,比如与宏的比较、编译器的处理机制、适用场景的限制以及如何查看是否内联成功。这些问题能帮助用户进一步深入理解内联函数的相关知识。</think>### C++内联函数详解 #### 一、核心概念 内联函数(inline function)是通过$inline$关键字声明的特殊函数,其核心机制是在**编译阶段将函数体直接插入调用位置**,消除传统函数调用的栈帧创建/销毁过程[^4]。这种特性使其成为C++性能优化的重要手段。 #### 二、核心作用与优势 | 特性 | 说明 | 对比传统函数调用 | |---------------------|--------------------------------------------------------------------|--------------------------| | **消除调用开销** | 省去参数压栈/退栈、返回地址保存等操作[^5] | 减少约3-10个CPU指令周期 | | **编译器优化窗口** | 展开后的代码可进行更激进的指令优化[^2] | 提升局部代码执行效率 | | **类型安全检查** | 相比C语言的宏函数,提供完整的类型系统支持[^2] | 避免宏替换导致的类型错误 | | **符号处理优化** | 允许在头文件中定义函数实现而不引发链接错误 | 简化代码组织结构 | #### 三、最佳使用场景 1. **高频微型函数**(5行以内最佳) ```cpp // 坐标点类中的getter方法 inline int Point::x() const { return m_x; } // 访问器理想候选 ``` 2. **简单数学运算** ```cpp inline Vector3 operator+(const Vector3& a, const Vector3& b) { return {a.x+b.x, a.y+b.y, a.z+b.z}; // 向量加法适合内联 } ``` 3. **模板元编程基础** ```cpp template<typename T> inline T min(T a, T b) { // 模板函数默认具有内联属性 return (a < b) ? a : b; } ``` #### 四、使用限制与注意事项 1. **禁止内联场景**(引用[3]) - 递归函数:无法确定展开深度 - 虚函数:动态绑定需要运行时机制 - 包含循环/复杂控制流的函数 2. **编译器决策权** ```cpp inline void bigFunction() { /* 200行复杂逻辑 */ } // 编译器可能拒绝内联请求[^3] ``` 3. **调试影响** - 内联函数在调试时无法设置断点 - 展开后的代码可能增加调试复杂度 #### 五、实战示例对比 ```cpp // 传统函数调用 double circleArea(double r) { return 3.1415926 * r * r; } // 内联版本 inline double inlineCircleArea(double r) { return 3.1415926 * r * r; } int main() { // 传统调用生成汇编代码示例: // push rbx // movsd xmm0, [rsp+20] // call circleArea double a = circleArea(5.0); // 内联展开示例: // movsd xmm0, [5.0] // mulsd xmm0, xmm0 // mulsd xmm0, [3.1415926] double b = inlineCircleArea(5.0); } ``` #### 六、现代编译器扩展 1. **自动内联机制**:现代编译器(如GCC/Clang)会对满足条件的小函数自动内联,即使没有$inline$关键字[^2] 2. **强制内联指令**: ```cpp __attribute__((always_inline)) // GCC特性 inline void criticalPathFunc() {...} ``` #### 七、性能验证方法 1. 查看汇编输出: ```bash g++ -S -O2 test.cpp # 生成汇编代码观察展开情况 ``` 2. 基准测试对比: ```cpp // 执行10亿次调用测试 auto start = high_resolution_clock::now(); for (int i=0; i<1e9; ++i) { result += func(i); // 测试不同版本的func } auto duration = high_resolution_clock::now() - start; ``` --相关问题-- 1. 如何通过编译器选项控制内联优化级别? 2. 内联函数与模板函数在实现机制上有何异同? 3. 什么情况下内联函数反而会降低程序性能? 4. 如何检测某个函数是否被成功内联展开?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值