Сохранение содержимого массива после завершения его вызова функции. (C ++) - PullRequest
1 голос
/ 03 августа 2009

Допустим, у меня есть следующий код.

double *return_array(void) {
   double foo[2];
   foo[0] = 5;
   foo[1] = 6;
   cout << foo << endl;
   cout << foo[0] << endl << foo[1] << endl;
   return foo;
}

double *bar = return_array()
cout << bar << endl;
cout << bar[0] << endl << bar[1] << endl;

Теперь, bar и foo - все тот же указатель, но то, что там было, полностью изменилось Как я могу обойти это? По сути, мне нужно передать 6 или 9 двойных от функции. Что мне делать?

Ответы [ 6 ]

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

Использовать вектор.

std::vector<double> return_array(void) {
   std::vector<double> foo;
   foo.push_back(5);
   foo.push_back(6);
   cout << foo[0] << endl << foo[1] << endl;
   return foo;
}

Это лучший способ, поэтому избегайте копирования вектора:

void fillVector(std::vector<double>& vec)
{
    vec.push_back(5);
    vec.push_back(6);
}

int main()
{
    std::vector<double> vec;

    fillVector(vec);
}

Теперь bar и foo остались прежними указатель но что там было изменилось полностью.

Поскольку foo размещается в стеке функции, он получает deallocatd, когда функция возвращается. Итак, bar на самом деле указывает не куда!

4 голосов
/ 03 августа 2009

Обычно вы передаете свою предварительно выделенную память в функцию:

int barsize = 2;
double *bar = new double[barsize];
fill_array( bar, barsize );
cout << bar << endl;
cout << bar[0] << endl << bar[1] << endl;
delete [] bar;

void fill_array( double *foo, int foosize )
{
  if ( foosize < 2 )
    return;

  foo[0] = 5;
  foo[1] = 6;
  cout << foo << endl;
  cout << foo[0] << endl << foo[1] << endl;
}

Правило, которое я использую: всегда выделять и удалять память в одном месте.

Или используйте std :: vector. Они хороши =) Я больше никогда не использую массивы.

1 голос
/ 03 августа 2009

Используйте new для выделения памяти, которая не ограничена функцией.

Не забудьте delete[] память, когда вы закончите с ней.

1 голос
/ 03 августа 2009

Выделите память в куче вместо стека, используя ключевое слово new:

double *return_array(void) {
    double * foo = new double [2];
    foo[0] = 5;
    foo[1] = 6;
    return foo;
}

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

double * foo = return_array();
// ...
delete [] foo;
0 голосов
/ 03 августа 2009

Если вы всегда возвращаете фиксированное количество элементов и готовы использовать расширения TR1 (или Boost), я бы выбрал std::tr1::tuple вместо vector или массив. Это шаблонный класс, так что вы захотите ввести его по-следующему:

typedef std::tr1::tuple<double, double, double, double, double, double> six_tuple;

Используйте make_tuple() с соответствующим числом (и типом) аргументов для создания кортежа, возвращаемого вашей функцией, и доступа к его содержимому с помощью шаблонной функции get<N>(), например ::

six_tuple foo = std::tr1::make_tuple(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
std::cout << std::tr1::get<0>(foo) << std::endl; // prints '1.0'

Компилятор проанализирует количество и типы аргументов для make_tuple() и выдаст ошибку, если вы попытаетесь присвоить неправильный тип кортежа.

Я предпочитаю это самому управлять памятью, но ваш пробег может отличаться.

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

Вы можете разместить результат в куче или, что еще лучше, использовать std :: vector.

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