C++函数详解(三)—— inline与constexpr函数、匹配和函数指针

本文详细介绍了C++中的内联函数和constexpr函数,讨论了它们的作用、使用场景以及如何放置在头文件中。此外,还探讨了函数匹配原则和函数指针的使用,包括定义、调用、作为形参和返回值的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 inline 与 constexpr 函数

1.1 内联函数

在函数签名的返回值类型前加上关键字inline,指示编译器将此函数作为内联函数,即在每个调用它的地方将其“内联地”展开(可以理解为在调用它的地方将调用函数代码替换为函数内部的实现代码)。常常将需要频繁调用且规模较小的轻量函数定义为内联函数,其意义如下:

  • 对于实现轻量操作的小函数而言,将其内部的轻量操作封装为一个小函数,而不是在需要执行这些轻量操作的地方直接写操作本身的代码,有利于程序的封装和复用。
  • 但如果这种封装的小函数只是普通的函数,而程序中需要对其频繁调用。因为函数调用隐式地包含了很多耗费资源的额外工作(如传参初始化形参临时对象等),因此在频繁调用的情景下会造成不必要的资源浪费。
  • 定义为内联函数,既满足了封装性,又避免了实际调用时带来的资源损耗。

需要注意两点:

  • 在函数签名中声明inline只是向编译器发出内联展开的请求,编译器可以根据情况忽略这个请求。一般不支持内联递归函数,且一个75行以上的函数也不大可能在调用点内联展开。
  • 除了显式地声明 inline外,还存在隐式内联函数。当类的一个成员函数在类内声明处定义时,编译器就会将其自动地优化为内联函数,这就是典型的隐式内联

范例:

//内联版本的shorterStr函数(返回两个string对象中较短的那个)
inline const string & shorterStr(const string &s1, const string &s2) {
   
   
	return s1.size() <= s2.size() ? s1 : s2;
}

int main() {
   
   
	string s1 = "aaaa", s2 = "bb";
	cout << shorterStr(s1, s2) << endl; //由于shorter是内联函数,在编译过程中,此语句被编译器展开为以下的形式:
	cout << s1.size() <= s2.size() ? s1 : s2; << endl;
}

class Array {
   
   
public:
	void func() {
   
    //在类内声明处定义,此函数隐式内联
		cout << "Array func" << endl;
	}
	void func1(); //func1在类内声明,类外定义
	inline void func2(); //func2在类内显式声明为内联函数,类外定义
	void func3(); //func3在类内没有显式声明为inline,在类外定义时追加inline
};
void Array::func1() {
   
    //func1在类内声明,类外定义,不会隐式自动优化为内联函数
	cout << "Array func1" << endl;
}
void Array::func2() {
   
    //func2在类内显式声明为内联函数,类外定义,编译器会在调用func2时尝试将其内联展开
	cout << "Array func2" << 
<think>好的,用户让我详细介绍一下C++函数。首先,我需要回忆一下用户之前的问题,之前他们问了关于前置自增后置自增的效率问题,现在转向了C++函数详解。这说明用户可能在学习C++的基础或者进阶知识,想深入理解函数的各个方面。 首先,我需要明确用户的需求。他们可能想要了解函数的基本结构、参数传递方式、高级特性等。作为刚学习C++的人,他们可能需要从基础开始,比如函数定义、返回值、参数等。但也不能排除他们可能已经有一定基础,想了解更深入的内容,比如函数重载、内联函数、lambda表达式等。 接下来,我需要考虑如何组织内容。用户之前的问题得到了结构清晰的回答,所以这次也应该保持类似的格式,分点讲解,结构清晰。可能需要分为函数基础、参数传递、高级特性、最佳实践等部分。 然后,用户可能想知道函数C++中的特殊之处,比如引用传递、函数重载、内联函数、lambda表达式等。这些都是C++相比其他语言的特点,需要详细解释。同时,用户可能对参数传递方式(值传递、指针传递、引用传递)的区别应用场景感兴趣,需要举例说明。 还要注意用户可能的实际应用场景,比如性能优化、代码可读性等。例如,内联函数适合短小代码,可以减少函数调用开销;lambda表达式在STL算法中的使用,这些实际例子能帮助用户理解。 另外,用户之前的问题涉及到效率问题,所以在介绍参数传递时,可以提到引用传递如何避免拷贝,提升效率,尤其是在处理大型数据结构时。同时,在最佳实践部分,强调合理选择参数传递方式的重要性,这之前的前置自增后置自增的效率讨论相呼应。 还要考虑用户可能的后续问题,比如函数重载模板函数的区别,或者lambda表达式的捕获列表等,所以在介绍时适当提及这些点,但不要过于深入,保持回答的简洁清晰。 最后,确保语言口语化,避免使用太多专业术语,或者在使用时加以解释,让不同层次的学习者都能理解。同时,检查是否有遗漏的重要知识点,比如默认参数、函数指针等,这些也是C++函数的重要组成部分,需要涵盖进去。 总结一下,我需要从基础到高级,分部分详细讲解C++函数的各个方面,结合示例代码,说明不同特性的使用场景注意事项,同时关联用户之前的问题,强调效率相关的知识点,帮助用户全面理解C++函数。</think>### C++ 函数详解 函数C++ 程序设计的核心模块,负责封装可重复使用的代码逻辑。以下是 C++ 函数的系统解析: --- #### **一、函数基础结构** ```cpp 返回值类型 函数(参数列表) { // 函数体 return 表达式; // 若返回值非 void 必须存在 } ``` **示例**: ```cpp int add(int a, int b) { return a + b; } ``` - **返回值类型**:定义函数输出结果的类型,`void` 表示无返回值 - **参数列表**:可接收零个或多个输入值,用逗号分隔 --- #### **二、参数传递方式** | 类型 | 语法示例 | 特点 | |-------------|-----------------|----------------------------------------------------------------------| | **值传递** | `void func(int x)` | 复制实参值到形参,函数内修改不影响原变量 | | **指针传递**| `void func(int* x)`| 直接操作内存地址,函数内修改会影响原变量 | | **引用传递**| `void func(int& x)`| 建立变量的别名(推荐方式),避免拷贝开销,可直接修改原变量 | **引用传递示例**: ```cpp void swap(int& a, int& b) { int temp = a; a = b; b = temp; } ``` --- #### **函数高级特性** 1. **函数重载 (Overload)** 允许同名函数通过参数列表的差异(类型/数量)实现不同功能: ```cpp void print(int x) { ... } void print(double x) { ... } void print(const string& s) { ... } ``` 2. **内联函数 (inline)** 通过避免函数调用开销优化小型函数: ```cpp inline int max(int a, int b) { return (a > b) ? a : b; } ``` - 适用于函数体简单、调用频繁的场景 - 由编译器决定是否真正内联 3. **默认参数** 为参数预设默认值,简化调用: ```cpp void draw(int x, int y, int color=0xFF0000) { // 调用时可省略 color 参数 } ``` - 默认参数必须从右向左连续设置 4. **Lambda 表达式 (C++11+)** 匿名函数的便捷实现方式: ```cpp auto sum = [](int a, int b) -> int { return a + b; }; sort(vec.begin(), vec.end(), [](int a, int b){ return a > b; }); ``` - 可捕获外部变量(`[=]` 值捕获,`[&]` 引用捕获) --- #### **四、特殊函数类型** | 类型 | 作用 | |-------------------|----------------------------------------------------------------------| | **递归函数** | 通过自我调用解决问题(需设置终止条件) | | **模板函数** | 支持泛型编程,适应多种数据类型 | | **constexpr 函数**| 在编译期计算结果(C++11+),用于优化常量表达式 | | **虚函数** | 实现多态性,通过基类指针/引用调用派生类的重写方法(面向对象核心特性) | --- #### **五、最佳实践建议** 1. **参数选择** - 优先使用引用传递(`const T&`)避免大型对象拷贝 - 需要修改原变量时使用引用,否则用 `const` 限定 2. **返回值优化** - 返回局部对象时,编译器可能进行返回值优化(RVO/NRVO) 3. **错误处理** - 通过返回值(错误码)、异常机制或 `std::optional`(C++17+)处理错误 --- ### **经典应用场景** 1. **数学计算**:封装复杂算法(如快速排序、矩阵运算) 2. **对象行为**:定义类成员函数实现面向对象特性 3. **回调机制**:通过函数指针或 `std::function` 实现事件驱动 4. **STL算法**:结合 Lambda 表达式自定义排序/过滤逻辑 通过合理设计函数接口控制副作用,可以显著提升代码的可维护性执行效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值