C++中if-else,switch-case有什么区别,执行效率哪个更高?是否其他语句有比两者更高的执行效率?

在编程中,选择使用 switch-case 还是 if-else 语句通常取决于代码的可读性、维护性和特定的使用场景。对于它们的性能,以下是对它们的效率比较:

1. 基本原理

  • if-else 语句

    • if-else 是一个链式结构,条件会一个一个被评估,直到找到第一个为真的条件为止。
    • 每个条件的计算都是线性的,最坏情况下,需要检查所有的条件。
  • switch-case 语句

    • switch-case 是一个多路分支结构,通常用于处理多个可能的值(通常是整数或枚举)。
    • 它会根据给定的表达式直接跳转到相应的分支,不必像 if-else 那样逐一检查条件。
    • 在大多数情况下,编译器可以将 switch-case 优化为跳转表或哈希表,使得分支选择几乎是常数时间复杂度。

2. 性能分析

  • 编译器优化

    • switch-case

      • 当分支数目较少时,编译器通常将其实现为一系列的条件检查(类似于 if-else)。
      • 当分支数目较多并且值是连续的(或几乎连续的),编译器可能会生成一个跳转表或哈希表,从而使得分支选择是常数时间复杂度 O(1)
      • 这种优化在处理大量可能的值时非常有效。
    • if-else

      • if-else 语句在编译器上通常被编译为一系列的条件跳转指令。
      • 如果条件是简单的布尔表达式,性能差别不大。
      • 如果条件是复杂的表达式或者包含多个条件,性能会受到评估顺序和表达式复杂性的影响。
  • 具体情境下的性能

    • 小范围分支
      • 当分支数目较少时(例如,2-3 个分支),if-elseswitch-case 的性能差别通常可以忽略不计。
      • 编译器在这种情况下可能会对两者做类似的优化。
    • 大范围分支
      • 对于多于几种可能性的分支,switch-case 通常会更高效,尤其是在可以优化为跳转表的情况下。
      • 在处理大型枚举或整数范围时,switch-case 通常会有显著的性能优势。

3. 代码可读性和维护性

  • if-else

    • if-else 适合于处理多种不同类型的条件(不仅限于整数值)。
    • 更灵活,可以处理任意复杂的逻辑。
    • 可读性和代码结构在面对简单的条件时可能更清晰。
  • switch-case

    • switch-case 在处理多个固定值时更直观。
    • 对于处理固定值集的逻辑(例如状态机、命令模式),switch-case 更具可读性和结构性。

4. 总结

  • 性能

    • 在处理少量分支时,两者差异不大。
    • 在处理大量固定值的分支时,switch-case 通常更高效。
  • 代码结构

    • if-else 适合处理复杂的条件和逻辑。
    • switch-case 适合处理大量固定值的情况,并且代码更简洁、可读。

 5.执行效率

如果if判断有很多条语句判断,如何提高执行效率。如下例子,提高执行效率可以这样改写。

std::string DataLoadULog::reNamePlot(std::string name)
{
if(name=="vehicle_attitude_setpoint/pitch_body")
{
std::string plotname="6.姿态角度/俯仰角_期望";
return plotname;
}
if(name=="vehicle_attitude_setpoint/roll_body")
{
std::string plotname="6.姿态角度/滚转角_期望";
return plotname;
}
if(name=="vehicle_attitude_setpoint/yaw_body")
{
std::string plotname="6.姿态角度/偏航角_期望";
return plotname;
}
//7.姿态角速度
if(name=="vehicle_rates_setpoint/pitch")
{
std::string plotname="7.姿态角速度/俯仰角速度_期望";
return plotname;
}
if(name=="vehicle_rates_setpoint/roll")
{
std::string plotname="7.姿态角速度/滚转角速度_期望";
return plotname;
}
if(name=="vehicle_rates_setpoint/yaw")
{
std::string plotname="7.姿态角速度/偏航角速度_期望";
return plotname;
}
//4.高度信息
if(name=="sensor_gps/alt")
{
std::string plotname="4.高度信息/海拔高度(GNSS高度)";
return plotname;
}
if(name=="trajectory_setpoint/z")
{
std::string plotname="4.高度信息/融合高度_期望";
return plotname;
}
if(name=="vehicle_local_position/z")
{
std::string plotname="4.高度信息/融合高度_测量";
return plotname;
}
if(name=="vehicle_air_data/baro_alt_meter")
{
std::string plotname="4.高度信息/气压高度";
return plotname;
}
if(name=="distance_sensor/current_distance")
{
std::string plotname="4.高度信息/雷达高度";
return plotname;
}}

DataLoadULog::reNamePlot 函数中,使用了一系列的 if-else 语句来匹配输入的 name 字符串并返回对应的字符串。这种方法在分支数目较多的情况下,可能会影响性能。要提高效率,我们可以考虑以下优化方法:

使用 std::unordered_map

使用 std::unordered_map 来存储键值对,这样可以利用哈希表来实现常数时间复杂度的查找。std::unordered_map 是 C++ 标准库提供的哈希表实现,非常适合这种键值匹配的场景。

以下是如何使用 std::unordered_map 重写 reNamePlot 函数:

#include <unordered_map>
#include <string>

class DataLoadULog {
public:
    std::string reNamePlot(const std::string& name);

private:
    static const std::unordered_map<std::string, std::string> plotNameMap;
};

// 定义并初始化 map
const std::unordered_map<std::string, std::string> DataLoadULog::plotNameMap = {
    {"vehicle_attitude_setpoint/pitch_body", "6.姿态角度/俯仰角_期望"},
    {"vehicle_attitude_setpoint/roll_body", "6.姿态角度/滚转角_期望"},
    {"vehicle_attitude_setpoint/yaw_body", "6.姿态角度/偏航角_期望"},
    {"vehicle_rates_setpoint/pitch", "7.姿态角速度/俯仰角速度_期望"},
    {"vehicle_rates_setpoint/roll", "7.姿态角速度/滚转角速度_期望"},
    {"vehicle_rates_setpoint/yaw", "7.姿态角速度/偏航角速度_期望"},
    {"sensor_gps/alt", "4.高度信息/海拔高度(GNSS高度)"},
    {"trajectory_setpoint/z", "4.高度信息/融合高度_期望"},
    {"vehicle_local_position/z", "4.高度信息/融合高度_测量"},
    {"vehicle_air_data/baro_alt_meter", "4.高度信息/气压高度"},
    {"distance_sensor/current_distance", "4.高度信息/雷达高度"}
};

// 函数实现
std::string DataLoadULog::reNamePlot(const std::string& name) {
    auto it = plotNameMap.find(name);
    if (it != plotNameMap.end()) {
        return it->second;
    }
    return ""; // 或者返回一个默认值
}

优点:

  • 效率高:查找时间复杂度为 O(1)。
  • 代码简洁:清晰地将输入与输出的映射分开,容易添加新的映射。
  • 易于维护:如果需要增加或修改映射,只需在 unordered_map 中添加或修改条目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会编程的程序猿ᅟ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值