DeepSeek 不用额外变量交换两个整数的值 C++实现
·
在 C++ 中,除了继承 C 的交换方法,还有更多现代和类型安全的选择。以下是各种实现方式:
方法1:现代 C++ 模板方法(推荐)
#include <iostream>
#include <utility> // 对于 std::swap
// 方法1:使用引用和算术运算
template<typename T>
void swap_arithmetic(T& a, T& b) {
// 防止同一变量交换
if (&a == &b) return;
a = a + b;
b = a - b;
a = a - b;
}
// 方法2:使用引用和异或运算
template<typename T>
void swap_xor(T& a, T& b) {
// 防止同一变量交换
if (&a == &b) return;
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
int main() {
int x = 10, y = 20;
std::cout << "交换前: x=" << x << ", y=" << y << std::endl;
swap_xor(x, y);
std::cout << "交换后: x=" << x << ", y=" << y << std::endl;
return 0;
}
方法2:使用 C++17 结构化绑定(仅展示概念)
#include <iostream>
#include <tuple>
// 演示概念:虽然实际创建了临时tuple,但思路有趣
void demo_structured_binding_concept(int& a, int& b) {
std::tie(a, b) = std::make_tuple(b, a);
}
int main() {
int x = 10, y = 20;
std::cout << "交换前: x=" << x << ", y=" << y << std::endl;
// 注意:这实际上创建了临时tuple,不算"无额外变量"
std::tie(x, y) = std::make_tuple(y, x);
std::cout << "交换后: x=" << x << ", y=" << y << std::endl;
return 0;
}
方法3:完美的零开销交换(C++11 之后)
#include <iostream>
#include <type_traits>
#include <bit> // C++20 位操作
// 安全的异或交换,仅对整数类型有效
template<typename T>
std::enable_if_t<std::is_integral_v<T>>
safe_xor_swap(T& a, T& b) noexcept {
// 使用 static_assert 确保类型安全
static_assert(std::is_integral_v<T>,
"XOR swap only works for integral types");
if (&a == &b) return; // 同一变量,无需交换
a ^= b;
b ^= a;
a ^= b;
}
// 通用的算术交换(可能溢出,需谨慎)
template<typename T>
void safe_arithmetic_swap(T& a, T& b) {
if (&a == &b) return;
// 检查是否可能溢出
if (std::is_integral_v<T>) {
if ((b > 0 && a > std::numeric_limits<T>::max() - b) ||
(b < 0 && a < std::numeric_limits<T>::min() - b)) {
// 可能溢出,使用其他方法
safe_xor_swap(a, b);
return;
}
}
a = a + b;
b = a - b;
a = a - b;
}
int main() {
int x = 10, y = 20;
unsigned short a = 30, b = 40;
std::cout << "交换前: x=" << x << ", y=" << y << std::endl;
safe_xor_swap(x, y);
std::cout << "交换后: x=" << x << ", y=" << y << std::endl;
std::cout << "\n交换前: a=" << a << ", b=" << b << std::endl;
safe_arithmetic_swap(a, b);
std::cout << "交换后: a=" << a << ", b=" << b << std::endl;
return 0;
}
方法4:C++ 类成员函数交换
#include <iostream>
class IntPair {
private:
int first, second;
public:
IntPair(int a, int b) : first(a), second(b) {}
// 成员函数:无临时变量交换
void swapMembers() {
if (&first == &second) return; // 理论上不会发生,但安全
first ^= second;
second ^= first;
first ^= second;
}
// 友元函数交换两个 IntPair 对象
friend void swapObjects(IntPair& p1, IntPair& p2) {
// 交换各自的成员
p1.first ^= p2.first;
p2.first ^= p1.first;
p1.first ^= p2.first;
p1.second ^= p2.second;
p2.second ^= p1.second;
p1.second ^= p2.second;
}
void print() const {
std::cout << "(" << first << ", " << second << ")";
}
};
int main() {
IntPair p1(10, 20);
IntPair p2(30, 40);
std::cout << "交换前: p1 = ";
p1.print();
std::cout << ", p2 = ";
p2.print();
std::cout << std::endl;
swapObjects(p1, p2);
std::cout << "交换后: p1 = ";
p1.print();
std::cout << ", p2 = ";
p2.print();
std::cout << std::endl;
return 0;
}
方法5:C++20 概念约束的现代实现
#include <iostream>
#include <concepts>
#include <type_traits>
// C++20 概念:可异或类型
template<typename T>
concept XorSwappable = requires(T a, T b) {
{ a ^ b } -> std::same_as<T>;
{ a ^= b } -> std::same_as<T&>;
};
// 仅支持可异或的类型
template<XorSwappable T>
void modern_xor_swap(T& a, T& b) noexcept {
if (&a == &b) return;
a ^= b;
b ^= a;
a ^= b;
}
// 通用的交换(使用移动语义,但这创建了临时对象)
template<typename T>
void modern_swap(T& a, T& b) noexcept {
// 注意:这使用了 std::move,实际上有临时对象
// 但编译器通常可以优化
T temp = std::move(a);
a = std::move(b);
b = std::move(temp);
}
int main() {
int x = 10, y = 20;
std::cout << "交换前: x=" << x << ", y=" << y << std::endl;
modern_xor_swap(x, y);
std::cout << "XOR 交换后: x=" << x << ", y=" << y << std::endl;
modern_xor_swap(x, y); // 换回来
std::cout << "再次 XOR 交换后: x=" << x << ", y=" << y << std::endl;
return 0;
}
实用的宏和 lambda 表达式
#include <iostream>
// 宏定义(不推荐在生产代码中使用,但有时有用)
#define XOR_SWAP(a, b) do { \
if (&(a) != &(b)) { \
(a) ^= (b); \
(b) ^= (a); \
(a) ^= (b); \
} \
} while(0)
// 使用 lambda 的交换
auto make_swapper = [](auto& a, auto& b) {
if (&a == &b) return;
a = a + b;
b = a - b;
a = a - b;
};
int main() {
int x = 100, y = 200;
std::cout << "交换前: x=" << x << ", y=" << y << std::endl;
// 使用宏
XOR_SWAP(x, y);
std::cout << "宏交换后: x=" << x << ", y=" << y << std::endl;
// 使用 lambda
make_swapper(x, y);
std::cout << "Lambda 交换后: x=" << x << ", y=" << y << std::endl;
return 0;
}
实际建议
- 生产代码:直接使用 std::swap,编译器会做最好的优化
- 面试/算法题:使用异或方法,记得检查同一变量
- 模板泛型:使用模板函数,增加类型安全
- 避免宏:使用内联函数或模板代替宏
// 最简单实用的 C++ 方式(虽然使用了临时变量,但最优)
#include <iostream>
#include <utility>
int main() {
int a = 10, b = 20;
std::cout << "Before: " << a << ", " << b << std::endl;
std::swap(a, b); // 标准库实现通常是最优的
std::cout << "After: " << a << ", " << b << std::endl;
return 0;
}
总结:在 C++ 中,虽然可以实现无临时变量的交换,但实际开发中通常优先使用 std::swap,因为:
- 可读性好
- 类型安全
- 编译器会优化
- 支持移动语义(C++11+)
- 适用于所有可移动构造和移动赋值的类型
更多推荐


所有评论(0)