2010-02-20 2 views
7

Предположим, что я есть массивВозвращает массив в C++

int arr[] = {...}; 
arr = function(arr); 

У меня есть функция, как

int& function(int arr[]) 
{ 
//rest of the code 
     return arr; 
} 

Какую ошибку я делаю здесь ??

+2

Почему вы (или просто любой разработчик) пишете этот сумасшедший код? : \ – kennytm

+0

@ manugupt1: Это ваше намерение передать массив в функцию в виде копии? –

ответ

7
int& function(int arr[]) 

В этой функции обр является указателем, и нет никакого способа, чтобы превратить его обратно в массив снова. Это то же самое, как

int& function(int* arr) 

int arr[] = {...}; 
arr = function(arr); 

Предполагая, что функция удалось вернуть ссылку на массив, то это еще не будет работать. Вы не можете назначить массив. В лучшем случае можно привязать результат к «ссылке массива X Интс» (с использованием ЬурейеГо, потому что синтаксис будет получить очень некрасиво иначе):

typedef int ten_ints[10]; 

ten_ints& foo(ten_ints& arr) 
{ 
    //.. 
    return arr; 
} 

int main() 
{ 
    int arr[10]; 
    ten_ints& arr_ref = foo(arr); 
} 

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


Если вы хотите массив фиксированного размера, которые можно присвоить и передавать по значению (с содержимым копируется), есть std::tr1::array (или boost::array). std::vector также является опцией, но это динамический массив, а не точный эквивалент.

1
  • Массив как аргумент на самом деле является указателем. Массивы автоматически «забрасываются» указателями, если они заданы как аргумент
  • Вы не можете назначить массив другому массиву в C/C++. Для копирования значений вам понадобится memcpy или loop.
  • Если функция изменяет аргумент arr, это фактически изменяет значение переменной arr, заданное вызывающим. Опять же, потому что массив на самом деле является указателем. Таким образом, в вызывающем абоненте arr назначается arr, что бесполезно здесь.
4

Семантика передачи и возврата массива может быть довольно запутанной. Вместо этого используйте std :: vector.

+0

или boost :: array, если это доступно. – Macke

+9

Хотя это, безусловно, хороший совет, ** он даже не отдаленно отвечает на вопрос ** .. –

+0

@Andreas «Какую ошибку я делаю здесь?» - ошибка использования вектора. – 2010-02-20 13:59:43

3

Вы возвращаете ссылку на int, а не ссылку на массив.

Вы хотите:

(int*)& function(int arr[]) 
{ 
    /// rest of the code 
    return arr; 
} 

Тем не менее, как и другие уже сказал, что это не является хорошей практикой.

+3

Фактически это возвращает ссылку на указатель, а 'arr' также не является массивом. –

+1

В дополнение к тому, что говорит @gf, это тоже синтаксическая ошибка. –

0

Хорошо, arr совместимо с int*, а не int&. Ваш код не будет компилироваться. Возможно, вы хотели return arr[0]?

6

Как утверждают другие, существуют лучшие варианты, такие как контейнеры STL, и наиболее интересный вопрос заключается в том, почему вам нужно вернуть массив к функции, которая уже имеет ее в области видимости.

Это, как говорится, вы не можете передавать или возвращать массивы по значению и нужно избегать массива затухающего к указателю (смотрите, например, here), либо с помощью указателей или ссылок на него:

int (&f(int (&arr)[3]))[3] 
{ 
    return arr; 
} 

Если вы не хотите жестко закодировать размер, вы можете использовать шаблон функции:

template<size_t n> 
int (&f(int (&arr)[n]))[n] 
{ 
    return arr; 
} 
+0

Это какой-то серьезный синтаксис _twisted_. Вы заслуживаете много наград за то, что даже получили это прямо здесь. Я могу свободно использовать typedefs, теперь я знаю, как вы могли бы написать это компилятору без _... +1 – sehe

+0

Предполагая, что я хотел бы закодировать getter для массива фиксированного размера и вы хотите, чтобы метод, а также ссылочный массив быть const - как бы я сделал это синтаксически? Пример: int const (& GetArray() const) [3] {return mArray; }? – Bjoern

+0

@Bjoern: 'typedef int A [3]; const A m; const A & f() const {return m; } '? –

0

используйте зЬй :: вектор, как это.

std::vector<int> function(const std::vector<int>& arr) 
{ 
    return arr; 
} 

массив как

int arr[] = {...}; 

не полезно быть возвращен из функции, потому что его не может копировать себя.

0

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

void foo(std::vector<int> &v) { 
    for (int i = 0; i < 10; ++ i) { 
     v.push_back(i); 
    } 
} 

, если вы используете:

std::vector<int> foo() { 
    std::vector<int> v; 
    for (int i = 0; i < 10; ++ i) 
     v.push_back(i); 

    return v; 
} 

там будет процесс копирования контейнера, стоимость дорого.

FYI: NRVO возможно исключить стоимость

1

Я думаю, что лучше всего вернуть его как указатель на массив. Вот пример:

{ 
    ... 
    int newLength = 0; 
    int* arr2 = ChangeArray(arr, length, newLength); 
    ... 
    delete[] arr2; 
} 

int* ChangeArray(int arr[], int length, int& newLength) 
{ 
    // reversing the number - just an example 
    int* newArr = new int[length]; 
    for(int i = 0; i < length; i++) 
    { 
     newArr[i] = arr[length-i-1]; 
     newLength++; 
    } 
    return newArr; 
} 
3

следующие работы и не кажется грязным или неправильно понятно!

int* returnarray(int a[]) 
{ 
    for (unsigned int i = 0; i < 3; i++) 
    { 
     a[i] *= 2; 
    } 
    return a; 
} 

int main(int argc, char* argv[]) 
{ 
    int arr[3] = {1,2,3}; 
    int* p = returnarray(arr); 
    for (unsigned int i = 0; i < 3; i++) 
    { 
     cout << "p[" << i << "] = " << p[i] << endl; 
    } 
     cin.get(); 
     return 0; 
}