【问题标题】:Swap arrays by using pointers in C++在 C++ 中使用指针交换数组
【发布时间】:2010-08-03 04:09:08
【问题描述】:

我有两个需要交换的指针数组。与其仅仅复制数组中的数据,不如交换指向数组的指针更有效。我一直认为数组名称本质上只是指针,但以下代码收到编译器错误:

double left[] = {1,2,3};
double right[] = {9,8,7};

double * swap = left;
left = right; // Error "ISO C++ forbids assignment of arrays"
right = swap; // Error "incompatible types in assignment of `double*' to `double[((unsigned int)((int)numParameters))]'"

动态创建数组可以解决问题,但无法在我的应用程序中完成。我该如何完成这项工作?

【问题讨论】:

  • 数组名不是指针。数组名是其第一个元素的地址。
  • 而指针是指向变量的地址。为什么我不能交换这些地址?
  • @thornate:数组名和指针变量之间最相关的区别是数组名不是左值,因此它不能成为赋值语句的目标。因此,做你想做的事情的方法是将数组名称分配给指针变量,左值,然后交换它们。一旦定义了“左”或“右”,就无法让它们指向其他任何东西。
  • @thornate 指针的 是变量的地址。指针名称本身并不像数组那样表示地址(您必须使用运算符& 来获取指针的地址)。在指针分配期间,一个指针的 被获取并分配给另一个指针。您不能在数组上这样做,因为根据语言概念,它们表示地址本身。据此,您正在尝试做类似0x23ff10 = 0x23ff44 的事情,假设左边是0x23ff10,右边是0x23ff44
  • @thornate:“我有两个指向双精度的指针数组”???在哪里?您的代码中没有任何“指针数组”。

标签: c++ arrays pointers swap


【解决方案1】:
double array_one[] = {1,2,3};
double array_two[] = {9,8,7};

double *left = array_one;
double *right = array_two;

double * swap = left;
left = right;
right = swap;

效果很好。

编辑: 不应使用定义 array_one 和 array_two 并且 doubleleft 和 doubleright 应该像您原来的 left 和 right 定义一样公开。

【讨论】:

  • 它只有在我想在那之后使用左右时才能很好地工作;我实际上需要交换 array_one 和 array_two,以便它们在调用这个的函数中也被交换。
  • @thornate 您的问题示例中没有任何功能。也许可以通过将指针传递给函数来解决?但是,如果您可以编辑您的帖子并解释您到底想要完成什么,那就更好了。
  • 它似乎并不总是有效。 std::swap() 在 C++ 中是一个更好的选择。
【解决方案2】:

数组与指针不同,不能以您描述的方式交换。要使用指针交换技巧,您必须使用指针,要么动态分配内存,要么使用指针访问数据(如 Daniel 所描述的那样)。

【讨论】:

  • 数组不是指针。数组不是指针。数组不是指针。 +1
  • 说到动态分配内存,你可以使用std::vector,它有一个swap()方法来交换底层指针。
【解决方案3】:

C 风格的数组不是指针,但与大多数对象一样,它们可以与标准的std::swap() 交换:

#include <iostream>
#include <utility>
int main()
{
        double array_one[] = {1,2,3};
        double array_two[] = {9,8,7};
        std::swap(array_one, array_two);
        std::cout << "array_one[0] = " << array_one[0] << '\n';
        std::cout << "array_two[0] = " << array_two[0] << '\n';
}

实际上,数组的 std::swap() 似乎只在 C++0x (20.3.2) 中定义,所以没关系。 正确的答案是,对于范围内的数组和作为指向第一个元素的指针的数组:

 std::swap_ranges(array_one, array_one + 3, array_two);

【讨论】:

  • 最佳和最简单的答案在这里。
【解决方案4】:

让人们相信它们不是指针并且不容易交换的最简单方法之一是显示以下代码:

struct ex {
  char c[4];
  double d[3];
};
struct ex a = {"foo", {1.0, 2.0, 3.0} };
struct ex b = {"bar", {6,7,8} };

现在显然 a.db.d 是数组。交换它们需要艰苦的工作,因为数组 {6,7,8} 必须在 a.c=="foo" 之后在内存中结束,这意味着复制 3 个双精度数。图片中没有指针。

【讨论】:

    【解决方案5】:

    试试这个

    double *right = (double[]){9,8,7};
    double *left = (double[]){8,2,3};   
    

    【讨论】:

    • 我无法更改数组的创建方式;它们被传递给我正在创建的函数,我无法编辑它们的定义方式。
    • 此语法是 C99 中没有的 C++ 功能
    【解决方案6】:

    您可以通过引用将两个指针传递给数组,如果指针不是 const,您可以交换它们:

    void swap(char * & first, char * & second)
    {
         std::swap(first, second);
    }
    

    【讨论】:

      【解决方案7】:

      声明数组时,名称为指针,不可更改。

      例如:

      int array[10];
      int *p;
      
      p = array; // legal
      array = p; // illegal; array is a constant pointer which can't be altered.
      

      实现交换的唯一方法是使用指向数组的新指针。

      这应该对你有帮助:

      SO question on array name as pointer

      【讨论】:

      • sizeof(array) 将证明array 不是指针。但它会在您需要时转换为指针。