收到C26497警告提示函数可改为constexpr,该函数是否适合改造?
你可以按照以下步骤确认函数是否存在未定义行为,以及是否适合改为constexpr:
- 第一步:检查整数溢出风险
你当前函数里所有计算都是signed int类型的乘法运算,signed int溢出属于C++标准明确规定的未定义行为。你可以先评估业务场景下iReminderInterval的合法取值范围:如果业务逻辑限定了该参数的最大值不会导致乘法结果超出int的取值范围(32位int最大可支持约2048周的间隔,完全覆盖日历提醒的常规使用场景),则不存在实际触发未定义行为的可能;如果存在参数超出合法范围的可能,可在函数开头加边界检查(比如用assert校验参数最大值,或者把计算类型换成无符号整数、std::int64_t等避免溢出)。 - 第二步:检查入参
iReminderUnitType的合法性
如果传入的iReminderUnitType不是ReminderUnitType枚举定义的合法值,你当前的逻辑会返回默认的1440分钟(1天),这是你代码显式定义的行为,不属于未定义行为,只要该默认逻辑符合业务预期就没有问题。 - 第三步:检查是否存在constexpr函数禁止的操作
你的函数没有动态内存分配、没有静态变量、没有修改外部状态、没有调用非constexpr函数,所有逻辑都是纯数值计算,完全符合C++17及更高版本中constexpr函数的语法要求。 - 第四步:编译期验证
你可以直接给函数加上constexpr修饰符,然后写一段编译期测试代码验证合法性,编译不报错就说明函数符合constexpr要求:
即使加了static_assert(CCalendarSettingsGooglePage::GetReminderIntervalAsMinutes(ReminderUnitType::Hours, 2) == 120); static_assert(CCalendarSettingsGooglePage::GetReminderIntervalAsMinutes(ReminderUnitType::Weeks, 1) == 10080);constexpr,原有的运行时调用逻辑也完全不受影响,不会破坏现有代码的兼容性。
如果想要进一步规避未定义行为的风险,可以在修改时增加参数校验逻辑,示例如下:
constexpr int CCalendarSettingsGooglePage::GetReminderIntervalAsMinutes(int iReminderUnitType, int iReminderInterval) noexcept { // 编译期+运行时参数校验,避免溢出风险,Debug模式下非法参数会触发断言 assert(iReminderInterval >= 0 && iReminderInterval <= 2048); int iMinutes = 24 * 60; // 默认值 if (iReminderUnitType == ReminderUnitType::Weeks) iMinutes = iReminderInterval * 7 * 24 * 60; else if (iReminderUnitType == ReminderUnitType::Days) iMinutes = iReminderInterval * 24 * 60; else if (iReminderUnitType == ReminderUnitType::Hours) iMinutes = iReminderInterval * 60; else if (iReminderUnitType == ReminderUnitType::Minutes) iMinutes = iReminderInterval; return iMinutes; }
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

