Возвращать массив в функции

Я использую гем под названием туннели, посмотрите здесь: https://github.com/jugyo/tunnels

Это прокси для http из https на вашем локальном машина. Также не нужны ключи.

Надеюсь, это поможет!

189
задан FunctionR 10 May 2014 в 07:55
поделиться

7 ответов

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

int fillarr(int arr[])

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

int fillarr(int* arr)

Так что в том же смысле то, что вы хотите вернуть из вашей функции, на самом деле является указателем на первый элемент массива:

int* fillarr(int arr[])

И вы все равно сможете использовать его так же, как и обычный массив:

int main()
{
  int y[10];
  int *a = fillarr(y);
  cout << a[0] << endl;
}
178
ответ дан 23 November 2019 в 05:39
поделиться

Функции C ++ не могут возвращать массивы в стиле C по значению. Самое близкое - вернуть указатель. Кроме того, тип массива в списке аргументов просто преобразуется в указатель.

int *fillarr( int arr[] ) { // arr "decays" to type int *
    return arr;
}

Вы можете улучшить его, используя ссылки на массив для аргумента и возврата, что предотвращает распад:

int ( &fillarr( int (&arr)[5] ) )[5] { // no decay; argument must be size 5
    return arr;
}

В Boost или C ++ 11 передача по ссылке является только необязательной, а синтаксис менее сложен. :

array< int, 5 > &fillarr( array< int, 5 > &arr ) {
    return arr; // "array" being boost::array or std::array
}

Шаблон array просто генерирует struct , содержащую массив в стиле C, поэтому вы можете применять объектно-ориентированную семантику, сохраняя при этом исходную простоту массива.

103
ответ дан 23 November 2019 в 05:39
поделиться

$ 8.3.5 / 8 состояния-

«Функции не должны иметь возвращаемый тип массива или функции типа, хотя они могут иметь возвращаемый тип указателя типа или ссылки на такие вещи. Не должно быть массивов функций, хотя могут быть массивы указателей на функции. "

int (&fn1(int (&arr)[5]))[5]{     // declare fn1 as returning refernce to array
   return arr;
}

int *fn2(int arr[]){              // declare fn2 as returning pointer to array
   return arr;
}


int main(){
   int buf[5];
   fn1(buf);
   fn2(buf);
}
19
ответ дан 23 November 2019 в 05:39
поделиться

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

std::vector<int> fillarr( std::vector<int> arr ) {
    // do something
    return arr;
}

Это сделает именно то, что вы от него ожидаете. Положительным моментом является то, что std :: vector заботится о том, чтобы все обрабатывались чисто. Обратной стороной является то, что это копирует очень большой объем данных, если ваш массив большой. Фактически он дважды копирует каждый элемент массива. сначала он копирует вектор, чтобы функция могла использовать его как параметр. затем он снова копирует его, чтобы вернуть вызывающему абоненту. Если вы можете справиться с управлением вектором самостоятельно, вам будет намного проще. (он может скопировать его в третий раз, если вызывающей стороне необходимо сохранить его в какой-либо переменной, чтобы произвести больше вычислений)

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

void fillarr(std::vector<int> &  arr) {
    // modify arr
    // don't return anything
}

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

Если вам действительно нужен новый экземпляр коллекции, но вы хотите, чтобы он не помещался в стек (и все связанное с этим копирование), вам необходимо создать какой-то контракт для обработки этого экземпляра. Самый простой способ сделать это - использовать интеллектуальный указатель, который сохраняет ссылочный экземпляр, пока кто-нибудь его удерживает. Он уходит чисто, если выходит за рамки. Это будет выглядеть так.

std::auto_ptr<std::vector<int> > fillarr( const std::vector<int> & arr) {
    std::auto_ptr<std::vector<int> > myArr(new std::vector<int>);
    // do stuff with arr and *myArr
    return myArr;
}

По большей части использование * myArr работает идентично использованию простого вектора ванили. В этом примере также изменяется список параметров путем добавления ключевого слова const . Теперь вы получаете ссылку, не копируя ее, но вы не можете ее изменить, поэтому вызывающий знает, что она будет такой же, как и до того, как функция добралась до нее.

Все это здорово, но идиоматический c ++ редко работает с коллекциями в целом. Обычно вы будете использовать итераторы для этих коллекций. это выглядело бы примерно так

template <class Iterator>
Iterator fillarr(Iterator arrStart, Iterator arrEnd) {
    Iterator arrIter = arrStart;
    for(;arrIter <= arrEnd; arrIter++)
       ;// do something
    return arrStart;
}

Использование этого выглядит немного странным, если вы не привыкли видеть этот стиль.

vector<int> arr;
vector<int>::iterator foo = fillarr(arr.begin(), arr.end());

foo теперь «указывает» на начало измененного arr .

Что действительно приятно в этом, так это то, что он одинаково хорошо работает с вектором, как с простыми массивами C, так и со многими другими типами коллекций, например

int arr[100];
int *foo = fillarr(arr, arr+100);

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

14
ответ дан 23 November 2019 в 05:39
поделиться

Это:

int fillarr(int arr[])

фактически обрабатывается так же, как:

int fillarr(int *arr)

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

int * fillarr(int arr[]){
    // do something to arr
    return arr;
}

. На самом деле это не возвращает массив. вы возвращаете указатель на начало адрес массива.

Но помните, что, передавая массив, вы передаете только указатель. Таким образом, когда вы изменяете данные массива, вы фактически изменяете данные, которые указатель указывает на. Поэтому перед тем, как передать массив, вы должны понять что у вас уже есть снаружи измененный результат.

например.

int fillarr(int arr[]){
   array[0] = 10;
   array[1] = 5;
}

int main(int argc, char* argv[]){
   int arr[] = { 1,2,3,4,5 };

   // arr[0] == 1
   // arr[1] == 2 etc
   int result = fillarr(arr);
   // arr[0] == 10
   // arr[1] == 5    
   return 0;
}

Я предлагаю вам рассмотреть возможность добавления длины в вашу функцию fillarr, например это.

int * fillarr(int arr[], int length)

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

Чтобы использовать его правильно. Сделайте что-нибудь вроде этого:

int * fillarr(int arr[], int length){
   for (int i = 0; i < length; ++i){
      // arr[i] = ? // do what you want to do here
   }
   return arr;
}

// then where you want to use it.
int arr[5];
int *arr2;

arr2 = fillarr(arr, 5);

// at this point, arr & arr2 are basically the same, just slightly
// different types.  You can cast arr to a (char*) and it'll be the same.

Если все, что вы хотите сделать, это установить для массива некоторые значения по умолчанию, рассмотрите возможность использования встроенная функция memset.

что-то вроде: memset ((int *) & arr, 5, sizeof (int));

Хотя я в теме. Вы говорите, что используете C ++. Посмотрите на использование векторов stl. Ваш код, вероятно, будет более надежным.

Есть много руководств. Вот тот, который дает вам представление о том, как их использовать. http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html

9
ответ дан 23 November 2019 в 05:39
поделиться

Вот полный пример этого вида проблемы, чтобы решить

#include <bits/stdc++.h>
using namespace std;
int* solve(int brr[],int n)
{
sort(brr,brr+n);
return brr;
}

int main()
{
int n;
cin>>n;
int arr[n];
for(int i=0;i<n;i++)
{
    cin>>arr[i];
}
int *a=solve(arr,n);
for(int i=0;i<n;i++)
{
    cout<<a[i]<<endl;
}

return 0;
}
0
ответ дан 23 November 2019 в 05:39
поделиться
int *fillarr(int arr[])

Вы все еще можете использовать результат вроде

int *returned_array = fillarr(some_other_array);
if(returned_array[0] == 3)
    do_important_cool_stuff();
2
ответ дан 23 November 2019 в 05:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: