在C++中使用指针交换数组

15

我有两个指向double的指针数组需要交换。不仅可以在数组内部复制数据,而且更高效的方法是仅交换指向数组的指针。我一直认为数组名本质上只是指针,但以下代码会收到编译器错误:

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))]'"

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


数组名不是指针。数组名是其第一个元素的地址。 - mip
1
指针是变量的地址。为什么我不能交换这些地址呢? - thornate
2
@thornate:数组名和指针变量之间最重要的区别是,数组名不是lvalue,因此不能成为赋值语句的目标。因此,要实现您想要的功能,需要将数组名分配给指针变量,这些变量是lvalue,然后交换它们。一旦定义了“left”或“right”,就无法使它们指向其他任何东西。 - Jim Lewis
@thornate指针的是一个变量的地址。指针名称本身不像数组那样表示地址(您必须使用运算符&来获取指针的地址)。在指针赋值期间,将取一个指针的并分配给另一个指针。您无法在数组上执行此操作,因为按照语言概念,它们本身表示地址。根据这个概念,您正在尝试做类似于0x23ff10 = 0x23ff44的事情,假设左边是0x23ff10,右边是0x23ff44 - mip
你所说的交换是指相应的数组值应该被交换,还是左侧和右侧的地址应该被交换? - sameerkn
显示剩余2条评论
7个回答

14
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_onearray_two不应该被使用,double* leftdouble* right应该像您原始的左右定义一样公开。


1
只有当我想在那一点之后使用左右时,它才能正常工作;实际上,我需要交换array_one和array_two,以便它们也在调用此函数的函数中被交换。 - thornate
@thornate 在你的问题示例中没有函数。也许可以通过传递指针给一个函数来解决它?但如果你能编辑你的帖子并解释你想要实现什么,那会更好。 - mip
它似乎并不总是有效。在C++中,std::swap()是一个更好的选择。 - Preetom Saha Arko

13

数组和指针并不相同,不能按照您描述的方式进行交换。要使用指针交换技巧,必须使用指针,动态分配内存或使用指针访问数据(如Daniel所述)。


14
数组不是指针。数组不是指针。数组不是指针。+1 - xtofl
1
说到动态分配内存,你可以使用std::vector,它有一个swap()方法来交换底层指针。 - JWWalker

5

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);

最好和最简单的答案在这里。 - Preetom Saha Arko

2

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

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个双精度浮点数。图片中没有指针。

0

试试这个

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

我无法更改数组的创建方式;它们被传递到我正在创建的函数中,我无法编辑它们的定义方式。 - thornate
1
这个语法是C99的特性,不在C++中。 - M.M

-1

你可以通过引用传递两个数组的指针,如果指针不是const类型,你可以直接交换它们:

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

-2

当您声明一个数组时,名称是一个指针,不能被更改。

例如:

int array[10];
int *p;

p = array; // legal
array = p; // illegal; array is a constant pointer which can't be altered.

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

这应该会对你有所帮助:

关于数组名作为指针的SO问题


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

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