C++指针交换

20

我正在编写一个交换指针的函数,但是我想不通为什么它不起作用。当我在swap函数中打印出r和s时,这些值已经被交换了,这让我相信我操作的是一份副本,但我不理解为什么因为我通过p和q的引用传递。

void swap(int *r, int *s)
{
    int *pSwap = r;
    r = s;
    s = pSwap;
    return;
}

int main()
{
    int p = 7;
    int q = 9;  
    swap(&p, &q);
    cout << "p = " << p << "q= " << q << endl;
    return 0;
}

输出:p = 7,q = 9


2
你正在操作指针的副本,而不是它们所指向的数据。更容易的方法是使用 std::swap(p, q);。或者,如果这个提议真的被采纳了,将来可以使用 p :=: q; - chris
3
@chris:哇。你能提供该提案的链接吗?(查询符号很困难。) - GManNickG
1
@GManNickG,好的,在这里。我对它能否通过有很大的疑虑。 - chris
@chris:抱歉,我是新手,正在尝试学习这个,如果我通过引用传递,那么我如何操作副本? - M K
@MK,指针本身是副本,你正在交换它们。你需要对它们进行解引用以获取它们所指向的内容并进行交换。 - chris
2
@MK:你需要解引用指针。但这很容易出错,因为它们可能为空,所以你应该使用引用。 (请注意,实际上您并没有通过引用传递任何内容。您正在传递值,这些值恰好是指针。) - GManNickG
7个回答

27

在你的swap函数中,你只是改变了指针的方向,即改变指针所指向的对象(在这里,具体来说是对象pq的地址)。但指针指向的对象本身并没有改变。

你可以直接使用std::swap,也可以像下面这样编写你的swap函数:

void swap(int *r, int *s)
{
   int temp = *r;
   *r = *s;
   *s = temp;
   return;
} 

2
我不清楚 OP 是想交换指针还是指针所指向的值。 - Shafik Yaghmour
@ShafikYaghmour 所做的是交换指针,因此我猜测 OP 希望交换指针所指向的值。 - taocp
@MK 你能修改一下你的问题,以便清楚地表明你不想修改指针而是它们所指向的内容吗? - Shafik Yaghmour
@ShafikYaghmour,你无法在物理上交换两个东西的地址。 - chris
@chris,没错,如果那是意图的话,答案会不同。 - Shafik Yaghmour
3
return语句不是无用的吗? - winklerrr

12

taocp所提供的被接受的答案也没有完全交换指针。以下是正确交换指针的方法。

void swap(int **r, int **s)
{
    int *pSwap = *r;
    *r = *s;
    *s = pSwap;
}

int main()
{
    int *p = new int(7);
    int *q = new int(9);

    cout << "p = " << std::hex << p << std::endl;
    cout << "q = " << std::hex << q << std::endl << std::endl;

    swap(&p, &q);

    cout << "p = " << std::hex << p << std::endl;
    cout << "q = " << std::hex << q << std::endl << std::endl;

    cout << "p = " << *p << " q= " << *q << endl;
    return 0;
}

我的机器上的输出:

p = 0x2bf6440
q = 0x2bf6460

p = 0x2bf6460
q = 0x2bf6440

p = 9 q= 7

我知道使用void *(在这种情况下是void **)并不被视为最佳实践,但考虑到每个指针实际上都是表示32/64位内存槽的std::size_t(无符号)变量,那么拥有void swap(void** A,void ** B)函数对于其他数据类型是否也更有效呢? - Danilo
你应该删除你分配的内存。在这个例子中并不是非常重要,但为了保持一致性,也是一个好的实践。 - undefined

1

这行代码 r=s 是将指针 r 的副本设置为指针 s 的副本。

如果您不想使用 std:swap,可以采用以下方法。

void swap(int *r, int *s)
{
    int tmp = *r;
    *r = *s;
    *s = tmp;
}

1
你传递了值的引用,这些值不是指针。因此,编译器创建临时的(int*)并将其传递给函数。
想一想p和q是什么:它们是变量,这意味着它们是在内存中分配的某个位置(在堆栈上,但这在这里不重要)。你怎么能谈论“交换指针”呢?好像你不能交换槽的地址。
你可以做的是交换两个容器持有的实际地址的值,而这些容器是指针。
如果你想交换指针,你必须创建指针变量,并将其传递给函数。
就像这样:
int p = 7;
int q = 9;

int *pptr = &p;
int *qptr = &q;
swap(pptr, qptr);
cout << "p = " << *pptr << "q= " << *qptr << endl;
return 0;

0
void swapPointer(int* &ptr1, int* &ptr2) {
    int* temp = ptr2;
    ptr2 = ptr1;
    ptr1 = temp;
}

可以通过使用引用来解决。


0

你的示例中没有使用按引用传递。这个版本是按引用传递的。

void swap2(int &r, int &s)
{
    int pSwap = r;
    r = s;
    s = pSwap;
    return;
}

int main()
{
    int p = 7;
    int q = 9;
    swap2(p, q);
    cout << "p = " << p << "q= " << q << endl;
    return 0;
}

按引用传递与按值或指针传递不同。请参阅网络上的C++教程以获取解释。我的大脑太小了,浪费细节存储单元,我可以轻松在网上找到。


这会交换值,而不是指针。通过将函数声明为引用,您刚刚改变了“swap”函数的语义。“r = s”当“r”和“s”是引用时,意思与“*p = *q”相同,当“p”和“q”是指针时。通过观察存储p和q的内存位置,在调试器上检查它。 - Euro Micelli

-2

如果你是喜欢 C 这门黑暗艺术的人,我建议使用这个宏:

#define PTR_SWAP(x, y)  float* temp = x; x = y; y = temp;

到目前为止,这对我来说是有效的。


问题涉及C ++。 - balu
@balu,C++已经包含了这个功能。 - jake_asks_short_questions

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接