Поменять массивы с помощью указателей в C ++ - PullRequest
11 голосов
/ 03 августа 2010

У меня есть два массива указателей на двойники, которые мне нужно поменять местами.Вместо того, чтобы просто копировать данные в массивах, было бы более эффективно просто поменять указатели на массивы.У меня всегда было впечатление, что имена массивов - это, по сути, просто указатели, но следующий код получает ошибку компилятора:

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

Динамическое создание массивов решило бы проблему, но в моем приложении это сделать невозможно,Как мне сделать эту работу?

Ответы [ 7 ]

12 голосов
/ 03 августа 2010

Массивы не совпадают с указателями и не могут быть заменены, как вы описываете. Чтобы выполнить трюк с обменом указателями, вы должны использовать указатели, либо динамически распределять память, либо использовать указатели для доступа к данным (как описал Дэниел).

12 голосов
/ 03 августа 2010
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;

Работает хорошо.

edit: Определения array_one и array_two не должны использоваться, а двойные left и double right должны быть общедоступнымикак ваши оригинальные левые и правые определения.

5 голосов
/ 03 августа 2010

Массивы в стиле 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);
2 голосов
/ 03 августа 2010

Один из самых простых способов убедить людей в том, что они не указатели и их не так просто поменять местами, - показать следующий код:

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.d и b.d - это массивы. Их замена потребует тяжелой работы, так как массив {6,7,8} должен заканчиваться в памяти после a.c=="foo", а это означает копирование 3 двойных. На картинке нет указателя.

0 голосов
/ 03 августа 2010

Вы можете передавать оба указателя в массивы по ссылкам, а если указатели не являются константными, вы можете просто поменять их местами:

0 голосов
/ 03 августа 2010

Когда вы объявляете массив, имя является указателем, который нельзя изменить.

Пример:

int array[10];
int *p;

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

Единственный способ добиться свопа - использовать новые указатели намассив.

Это должно помочь вам:

ТАК вопрос об имени массива в качестве указателя

0 голосов
/ 03 августа 2010

Попробуйте это

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