1018 字
5 分钟
全用if不只是性能问题

if与if-else的差异#

核心差异#

特性只使用ifif-else
执行逻辑所有条件都会检查遇到第一个真条件后停止检查
互斥性多个条件可能同时执行最多执行一个分支
性能可能较低(检查所有条件)通常较高(短路执行)
逻辑清晰度适用于独立条件适用于互斥条件

具体示例#

只使用if#

这是一段注册功能的java代码,每个if所对应的检查都有明确的目的和错误处理

/**
* 用户注册功能
* @param username 用户名
* @param password 密码
* @param email 邮箱
* @param userType 用户类型
* @return 注册成功返回用户信息,用户名已存在返回null
*/
@Override
public Map<String, Object> register(String username, String nickname, String password, String email, UserTypeEnum userType) {
LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
userQueryWrapper.eq(User::getUsername, username);
User existingUser = userMapper.selectOne(userQueryWrapper);
if (existingUser != null) {
throw new ApiException(ExceptionEnum.USER_EXIST);
}
// 检查邮箱是否已存在
if (email != null && !email.isEmpty()) {
LambdaQueryWrapper<User> emailQueryWrapper = new LambdaQueryWrapper<>();
emailQueryWrapper.eq(User::getEmail, email);
User emailUser = userMapper.selectOne(emailQueryWrapper);
if (emailUser != null) {
throw new ApiException(ExceptionEnum.EMAIL_EXIST);
}
}
// 创建新用户
User user = User.builder()
.username(username)
.nickname(nickname)
.password(passwordEncoder.encode(password))
.email(email)
.userType(userType != null ? userType : UserTypeEnum.STUDENT)
.deleted(false)
.createdAt(LocalDateTime.now())
.updatedAt(LocalDateTime.now())
.lastLoginAt(LocalDateTime.now())
.build();
userMapper.insert(user);
UserSimpleVO userVO = userConverterUtils.toUserSimpleVO(user);
// 生成JWT token
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
String token = jwtTokenUtil.generateToken(userDetails);
// 返回结果
Map<String, Object> result = new HashMap<>(8);
result.put("token", token);
result.put("user", userVO);
result.put("message", "注册成功");
return result;
}

检查用户名和检查邮箱是两个独立的过程,即使用户名已存在,我们可能仍然想知道邮箱是否也被占用(或者反之),因此使用独立的if是合理的

if-else#

一个签到题的c++题解 原题是一道判定n变为3的倍数所需增加多少量的题

#include <iostream>
using namespace std;
int main(){
int t;
cin >> t;
for (int i = 0; i < t; i++){
int n;
cin >> n;
if (n % 3 == 0){
cout << 0 << endl;
}
else{
cout << 3 - (n % 3) << endl;
}
}
return 0;
}

n除以3不余0的情况自然便是else
不过此题全用if也不会WA,顶多慢一点

我是怎么WA的#

原题(洛谷上的):P1563 [NOIP 2016 提高组] 玩具谜题

预期逻辑:对于每条指令,根据当前小人x的朝向(p[x]) 和指令方向(a[i]),二选一地决定是顺时针还是逆时针移动

WA的代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll p[100010] = {0};
string name[100010] = {};
ll a[100010] = {0};
ll s[100010] = {0};
int main (){
ll n,m;
cin >> n >> m;
for (ll i = 0; i < n; i++){
cin >> p[i] >> name[i];
}
for (ll i = 0; i < m; i++){
cin >> a[i] >> s[i];
}
int x = 0;
for (ll i = 0; i < m; i++){
if ((p[x] == 0 && a[i] == 1) || (p[x] == 1 && a[i] == 0)){
x = (x + s[i]) % n;
}
if ((p[x] == 1 && a[i] == 1) || (p[x] == 0 && a[i] == 0)){
x = (x - s[i] % n + n) % n;
}
}
cout << name[x];
return 0;
}

AC的代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll p[100010] = {0};
string name[100010] = {};
ll a[100010] = {0};
ll s[100010] = {0};
int main (){
ll n,m;
cin >> n >> m;
for (ll i = 0; i < n; i++){
cin >> p[i] >> name[i];
}
for (ll i = 0; i < m; i++){
cin >> a[i] >> s[i];
}
int x = 0;
for (ll i = 0; i < m; i++){
if ((p[x] == 0 && a[i] == 1) || (p[x] == 1 && a[i] == 0)){
x = (x + s[i]) % n;
}
else {
x = (x - s[i] % n + n) % n;
}
}
cout << name[x];
return 0;
}

可以看到,两者间只把if改成else,差距却一个WA一个AC
乍看上去两者相差不大,都正确包含了所需情况
然而只使用if会导致第二个if在意料之外被执行

由于每个if语句执行后x会变,而x又是条件语句中的一部分
于是就出现了这样的情况
在第一个if更新当前位置x后,第二个if使用更新后的x来判断朝向
这与我们程序的目的显然不符

正确的做法是使用if-else结构,确保每条指令都基于指令执行前的位置x的朝向来决定移动方向

全用if不只是性能问题
https://shuntianyifang.github.io/shuntian-blog/posts/post4/全用if不只是性能上的问题/
作者
顺天一方
发布于
2025-11-10
许可协议
CC BY-NC-SA 4.0