C++ 异常捕获与普通函数的对象传递区别

引用自:《More Effective C++》

第一、异常对象在传递时总被进行拷贝;当通过传值方式捕获时,异常对象被拷贝了两次。对象做为参数传递给函数时不一定需要被拷贝。
注:异常对象抛出时一定会进行一次拷贝,捕获时使用引用传递就不需要拷贝了。作为参数被传递给函数时,函数处可能是引用参数,就不需要复制对象。

第二、对象做为异常被抛出与做为参数传递给函数相比,前者类型转换比后者要少(前者只有两种转换形式)。
注:前者智能转换继承类为基类、指针到空指针;后者可以各种隐式转换。

第三、catch 子句进行异常类型匹配的顺序是它们在源代码中出现的顺序,第一个类型匹配成功的 catch 将被用来执行。当一个对象调用一个虚拟函数时,被选择的函数位于与对象类型匹配最佳的类里,即使该类不是在源代码的最前头。

### C++11 Lambda 表达式函数对象区别使用场景 #### 一、Lambda 表达式的特性 Lambda 表达式是 C++11 中引入的一种简洁方式,用于创建匿名函数。它的主要优势在于能够简化代码并提高可读性。通过捕获上下文中的变量,Lambda 可以方便地访问局部作用域内的数据[^1]。 以下是 Lambda 表达式的一个典型例子: ```cpp #include <iostream> int main() { auto add = [](int a, int b) -> int { return a + b; }; std::cout << "Result: " << add(3, 4) << std::endl; return 0; } ``` Lambda 的语法结构通常由以下几个部分组成: - **捕获列表**:指定哪些外部变量被 Lambda 捕获以及如何捕获(值传递还是引用传递)。 - **参数列表**:类似于普通函数参数声明。 - **返回类型**(可选):如果无法自动推导,则需显式指定。 - **函数体**:执行逻辑所在的部分。 #### 二、函数对象的特点 函数对象是指可以通过 `operator()` 调用的对象。它们本质上是一个类实例,在该类中实现了重载的括号运算符[]。相比于普通函数指针或 Lambda 表达式,函数对象提供了更大的灵活性,允许封装状态其他成员变量。 下面展示了一个简单的函数对象定义及其应用: ```cpp #include <iostream> struct Adder { int base_value; explicit Adder(int value) : base_value(value) {} int operator()(int increment) const { return base_value + increment; } }; int main() { Adder my_adder{5}; std::cout << "Add Result: " << my_adder(7) << std::endl; return 0; } ``` 在这个例子中,`Adder` 类不仅包含了加法功能还保存了初始值作为内部状态的一部分。 #### 三、两者的主要区别 | 特性 | Lambda 表达式 | 函数对象 | |---------------------|--------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------| | 定义形式 | 内联定义,无需额外命名 | 需要单独定义一个类 | | 状态管理 | 支持通过捕获机制获取外部变量 | 自然支持复杂的状态管理多态行为 | | 性能 | 编译器优化良好,运行效率高 | 同样高效,但在某些情况下可能涉及虚表开销 | | 复杂度 | 更适合轻量级任务 | 对于需要维护大量状态或者继承关系的任务更加适用 | 尽管 Lambda 是一种强大的工具,但它仍然只是函数对象的一种特殊表现形式——即无名版本。因此当面对较为复杂的业务需求时,统意义上的函数对象往往更具优势。 #### 四、实际应用场景对比分析 对于一些小型回调函数来说,采用 Lambda 显得更为直观便捷;而涉及到长期存在的算法组件或者是那些需要频繁修改其属性的情况,则应该优先考虑设计专门的函数对象[^2]^。 例如标准库容器配合 STL 算法时经常需要用到自定义比较规则的情形下,两种方案均可胜任但各有侧重: ##### 使用 Lambda 实现快速排序定制化比较规则 ```cpp std::vector<int> numbers = {5, 8, 2, 9, 1}; std::sort(numbers.begin(), numbers.end(), [](const int& lhs, const int& rhs){return lhs > rhs;}); // 结果按照降序排列 ``` ##### 利用 Function Object 达成相同目的的同时具备扩展能力 ```cpp class DescendingComparator{ public: bool operator () (const int &lhs,const int &rhs)const{return lhs>rhs;} }; std::vector<int> nums={5,8,2,9,1}; std::sort(nums.begin(),nums.end(),DescendingComparator()); // 这里也可以很容易加入更多字段参比较等高级操作 ``` 综上所述,虽然二者都能满足大多数编程需求,但是在特定条件下选择合适的技术手段才能更好地发挥各自特长[^3].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值