Как мне вернуть массив из функции? - PullRequest
0 голосов
/ 14 ноября 2010

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

#include <iostream>
using namespace std;

struct Coord{
 int r;
 int c;
 };
struct CoordwValue{
 Coord C;
 char Value;
 };

CoordwValue* getNeighbors();

int main (){
 CoordwValue *k= getNeighbors();
 for (int i=0;i<4;i++)
  cout<<(k[i].Value);
}
CoordwValue *getNeighbors(){
 CoordwValue Neighbors[4];
 Neighbors->Value='X';
 Neighbors->C.r= 0;
 Neighbors->C.c= 1;
 (Neighbors+1)->Value='0';
 (Neighbors+1)->C.r= 1;
 (Neighbors+1)->C.c= 2;
 (Neighbors+2)->Value='1';
 (Neighbors+2)->C.r= 2;
 (Neighbors+2)->C.c= 1;
 (Neighbors+3)->Value='X';
 (Neighbors+3)->C.r= 1;
 (Neighbors+3)->C.c= 0;
 //for (int i=0;i<4;i++)
 // cout<<Neighbors[i].Value;
 return Neighbors;
 }

Эта часть кода печатает X01X

for (int i=0;i<4;i++)
  cout<<Neighbors[i].Value;

Но яне может получить тот же результат от

for (int i=0;i<4;i++)
  cout<<(k[i].Value);

В чем проблема?

Редактировать:

Эта версия кода работает нормально.

#include <iostream>
using namespace std;


char* getNeighbors();

int main (){
    char *k= getNeighbors();
    for (int i=0;i<4;i++)
        cout<<(*(k+i));
}
char *getNeighbors(Coord C, int r){
    char Neighbors[4];
    *Neighbors='X';
    *(Neighbors+1)='0';
    *(Neighbors+2)='1';
    *(Neighbors+3)='X'
    return Neighbors;
    }

Ответы [ 5 ]

4 голосов
/ 14 ноября 2010

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

CoordwValue *Neighbors = new CoordwValue[4];

Вместо этого:

CoordwValue Neighbors[4];

Конечно, тогда до вызывающей функции (в нашем случае main) нужно правильно delete[] массив, когда он завершит его использование.

3 голосов
/ 14 ноября 2010

Если вы хотите вернуть массив из четырех объектов, вам не обязательно использовать динамическое выделение или std::vector.Вам просто нужно обернуть массив в классе, чтобы вы могли его вернуть.Например:

struct GetNeighborsResult
{
    CoordwValue Value[4];
};

GetNeighborsResult getNeighbors();

Boost, TR1 и C ++ 0x имеют контейнерный шаблон класса array, который вы можете легко использовать для этой цели:

std::array<CoordwValue, 4> getNeighbors();

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

Если вы решили вернуть указательдля динамически распределяемого массива используйте умный указатель для управления памятью.Нет никаких оснований не использовать умный указатель.

1 голос
/ 14 ноября 2010

Возвращенный массив создается на stack и возвращается. Я бы посоветовал прочитать о разнице кучи и стековой памяти здесь .

Если массив должен быть возвращен из функции, у вас есть возможность динамически распределять память, используя new. Однако затем память должна быть освобождена с delete, иначе это приведет к утечке памяти.

STL контейнеры используют динамическую память и перегружены copy constructor. Замена массива на vector<T> позволит вам безопасно возвращать значения.

0 голосов
/ 14 ноября 2010

Вы возвращаете адрес локальной переменной.Когда getNeighbors возвращается, Neighbors[4] выходит из области видимости, вызывая всевозможные проблемы, в том числе то, что должно быть предупреждением / ошибкой компилятора.

У вас есть несколько вариантов этого: во-первых, делать то, что cdhowieсказал и вернуть динамически распределенный массив.Другой - возвращать по значению, поэтому возвращаемое значение - это КОПИЯ Neighbors[4], а не указатель на него.Я думаю, что синтаксис для этого будет что-то вроде CoordwValue getNeighbors()[4] { .... }

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

0 голосов
/ 14 ноября 2010

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

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

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