【问题标题】:Should I reference elements of arrays when working with them?我应该在使用数组时引用它们的元素吗?
【发布时间】:2021-02-04 15:18:14
【问题描述】:

假设我们要使用以下代码实现冒泡排序:

void bubbleSort(int arr[], int n){
    for(int i=0; i<n-1; i++){
        for(int j=i+1; j<n;j++){
            if(arr[i]>arr[j]){
                swap(arr[i], arr[j]);
            }
        }
    }
}

swap 函数中arr[i]arr[j] 之前是否应该有一个&amp;,有什么区别?我记得在某处读到不需要将&amp; 符号放在数组元素之前以便直接使用地址。我知道这是一个愚蠢的问题,所以请原谅我问这个问题,但是这些小细节有助于我更好地理解指针。

【问题讨论】:

  • std::swap 函数已通过引用获取其参数。
  • type_name &amp; variable_name 提供参考。 &amp;variable_name(大部分时间)生成一个指针。
  • 虽然数组本身可以衰减为指向其第一个元素的指针,但数组元素不会自动转换为指针。数组中的int 与任何其他int 之间没有区别。
  • 请注意,一元“地址”运算符&amp; 与类型中使用的“引用”&amp; 完全无关。
  • 通常,在 C++ 中,函数是通过值还是通过引用获取参数是函数的属性以及它如何声明其参数。您不需要告诉调用站点参数是如何传递的。在 C 中,因为不存在引用类型,所以实现传递引用的唯一方法是使用指针。在这种情况下,您需要使用&amp; 来获取调用站点的参数地址。有时在 C++ 中仍然会发生这种情况,但 ir 应该是例外。

标签: c++ arrays pointers swap


【解决方案1】:

交换函数中arr[i]和arr[j]之前是否应该有&

取决于swap 接受的参数类型。

如果您问的是 C++ 标准库的 std::swap,那么:不,不应该有运算符 &。

会有什么不同?

一元&运算符是运算符的地址。结果是一个指向操作数的纯右值指针。

std::swap 的参数是对非常量的引用,因此不能绑定到右值参数。此外,那将是交换指针;不是元素的值。

可以std::iter_swap(&amp;arr[i], &amp;arr[j]),因为std::iter_swap间接通过参数迭代器并交换指向的对象......但这会不必要地复杂。我不建议在这种情况下使用它。

或者,std::iter_swap(arr + i, arr + j) 也可以使用。


一些例子:

// similar to std::swap
void swap1(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

swap1(arr[i], arr[j]);

// similar to std::iter_swap
void swap2(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

swap2(arr + i, arr + j);
swap2(&arr[i], &arr[j]);

【讨论】:

    【解决方案2】:

    函数std::swap 具有引用类型的参数。所以这个电话

    swap(arr[i], arr[j]);
    

    交换引用的对象arr[i]arr[j]

    如果你会这样写

    swap(&arr[i], &arr[j]);
    

    然后编译器将发出错误,因为您正在传递右值并且您可能无法将右值与左值引用绑定。

    您可以编写自己的 swap 函数,该函数通过 C 中的引用接受参数,即当对象通过指向它们的指针间接传递给函数时。

    这是一个演示程序。

    #include <iostream>
    #include <utility>
    
    using namespace std;
    
    void swap( int *px, int *py )
    {
        int tmp = *px;
        *px = *py;
        *py = tmp;
    }
    
    int main() 
    {
        int x = 5, y = 10;
        
        cout << "x = " << x << ", y = " << y << '\n';
        
        swap( x, y );
        
        cout << "x = " << x << ", y = " << y << '\n';
    
        swap( &x, &y );
        
        cout << "x = " << x << ", y = " << y << '\n';
    
        return 0;
    }
    

    它的输出是

    x = 5, y = 10
    x = 10, y = 5
    x = 5, y = 10
    

    在本次通话中

    swap( x, y );
    

    这里使用了重载的标准函数std::swap,因为它的参数是左值。

    在本次通话中

    swap( &x, &y );
    

    之所以称为重载用户定义函数swap,是因为它的参数是右值(临时对象),编译器会选择最合适的用户定义函数。

    【讨论】:

      【解决方案3】:

      template&lt; class T &gt; void swap( T&amp; a, T&amp; b );

      这是 std::swap() 的定义。

      如你所见,它获取元素的地址

      来源:https://en.cppreference.com/w/cpp/algorithm/swap

      【讨论】:

      • 抱歉,您并没有澄清 OP 对引用与指针的混淆,而是对此做出了贡献。
      猜你喜欢
      • 2011-01-11
      • 1970-01-01
      • 2018-06-01
      • 2012-12-03
      • 1970-01-01
      • 1970-01-01
      • 2014-04-09
      • 1970-01-01
      • 2017-06-13
      相关资源
      最近更新 更多