有没有办法交换 2 个结构?

Is there a way to swap 2 structs?

在 C++ 中,您可以交换两个数字而无需第三个变量:

int x = 10;
int y = 5;
x ^= y; 
y ^= x; 
x ^= y; //x = 5, y = 10

所以我想知道是否有类似的方法可以在没有第三个变量的情况下交换 2 个结构:

struct Position{int x, y;};
int main()
{
   Position firstPose{x = 10, y = 5;};
   Position secPose{x = 5, y = 10;};
   //Now I want to swap firstPose with secPose.
}

这可能吗?如果是这样;怎么做

是的,有一些方法可以达到您的要求。但是,请注意,在两个值之间交换的 XOR 方法效率很低。

首先,让我们假设所需的结构:

struct position {
    int x;
    int y;
};

方法一

创建您自己的 swap() 函数:

void swap(position &pos1, position &pos2) {
    // Swapping X
    verify_overflow(pos1.x, pos2.x); // See about this below
    pos1.x = pos1.x + pos2.x;
    pos2.x = pos1.x - pos2.x;
    pos1.x = pos1.x - pos2.x;

    // Swapping Y
    verify_overflow(pos1.y, pos2.y); // See about this below
    pos1.y = pos1.y + pos2.y;
    pos2.y = pos1.y - pos2.y;
    pos1.y = pos1.y - pos2.y;
}

现在,你可以这样实现它:

swap(v1, v2);

注意:为了防止由于溢出导致的未定义行为,可以使用以下子例程:

inline void verify_overflow(signed int si_a, signed int si_b) {
    signed int sum;

    if (__builtin_sadd_overflow(si_a, si_b, &sum)) {
        std::cerr << "[error] Overflow is possible to happen.\n";
        exit(1);
    }
}

例如,当你设置一个结构时:

position v1 = {2147483647, 2147483644};

程序会报如下错误,UB不会出现:

[error] Overflow is possible to happen.

方法二

C++ 标准中已经内置了 std::swap()。它的好处是当结构改变时你不需要继续改变代码。代码应如下所示:

#include <iostream>

struct position {
    int x;
    int y;
};

int main(void) {
    position v1 = {5, 10};
    position v2 = {10, 5};

    std::swap(v1, v2);

    std::cout << v1.x << ' ' << v1.y << std::endl;
    std::cout << v2.x << ' ' << v2.y << std::endl;

    return 0;
}

没有中间副本交换两个结构的标准方法。可以说,交换的主要好处之一“是”中间副本,这篇精彩的文章解释了交换如何成为实现“强异常保证”的关键部分。 https://www.stroustrup.com/except.pdf

此外,如果目标是不复制结构(因为是资源密集型),您可以使用 pimpl 惯用语设计 class 并仅交换指针(您仍然会有第三个变量,但它只是指向结构的原始指针)。

如果您想有效地使用 C++ 让自己熟悉异常安全,它确实是该语言最擅长的领域

有点老但还是不错的文章:http://www.gotw.ca/gotw/008.htm

最后,最终的解决方案是创建一个自定义交换函数:

#include <iostream>
#include <string>

struct Position{int x, y;};

void swap(Position& a, Position& b)
{
    a.x ^= b.x; 
    b.x ^= a.x; 
    a.x ^= b.x;

    a.y ^= b.y; 
    b.y ^= a.y; 
    a.y ^= b.y; 
}

int main()
{
    Position a = { 10, 100};
    Position b = { 20, 200};
  
    swap(a, b);
    std::cout << "a:" << a.x << "," << a.y << std::endl;
    std::cout << "b:" << b.x << "," << b.y << std::endl;
}

恕我直言,最后一个选项更多的是个人娱乐而不是真正的生产代码。