Como retornar um array de uma function?

Como posso retornar um array de um método e como devo declará-lo?

int[] test(void); // ?? 

int* test();

mas seria “mais C ++” para usar vetores:

std::vector< int > test();

EDITAR
Eu vou esclarecer algum ponto. Desde que você mencionou o C ++, eu vou com new[] operadores new[] e delete[] , mas é o mesmo com malloc / free.

No primeiro caso, você vai escrever algo como:

 int* test() { return new int[size_needed]; } 

mas não é uma boa ideia porque o cliente da sua function realmente não conhece o tamanho da matriz que você está retornando, embora o cliente possa desalocá-lo com segurança com uma chamada para delete[] .

 int* theArray = test(); for (size_t i; i < ???; ++i) { // I don't know what is the array size! // ... } delete[] theArray; // ok. 

Uma assinatura melhor seria esta:

 int* test(size_t& arraySize) { array_size = 10; return new int[array_size]; } 

E o seu código de cliente seria agora:

 size_t theSize = 0; int* theArray = test(theSize); for (size_t i; i < theSize; ++i) { // now I can safely iterate the array // ... } delete[] theArray; // still ok. 

Como este é o C ++, o `std :: vector é uma solução amplamente usada:

 std::vector test() { std::vector vector(10); return vector; } 

Agora você não precisa chamar delete[] , pois ele será manipulado pelo object e você pode iterá-lo com segurança com:

 std::vector v = test(); std::vector::iterator it = v.begin(); for (; it != v.end(); ++it) { // do your things } 

o que é mais fácil e seguro.

Como posso retornar uma matriz em um método de c ++ e como devo declará-lo? int [] teste (void); ??

Isso parece uma pergunta simples, mas em C ++ você tem algumas opções. Em primeiro lugar, você deve preferir …

  • std::vector<> , que cresce dinamicamente para quantos elementos você encontra em tempo de execução, ou

  • std::array<> (introduzido com C ++ 11), que sempre armazena um número de elementos especificados em tempo de compilation,

… como eles gerenciam a memory para você, garantindo o comportamento correto e simplificando consideravelmente as coisas:

 std::vector fn() { std::vector x; x.push_back(10); return x; } std::array fn2() // C++11 { return {3, 4}; } void caller() { std::vector a = fn(); const std::vector& b = fn(); // extend lifetime but read-only // b valid until scope exit/return std::array c = fn2(); const std::array& d = fn2(); } 

A prática de criar uma referência const para os dados retornados pode, às vezes, evitar uma cópia, mas normalmente você pode confiar apenas na Otimização de Valor de Retorno, ou – para vector mas não em semântica de movimentação de array (introduzida com C ++ 11).

Se você realmente quiser usar uma matriz embutida (diferente da class de biblioteca padrão chamada array mencionada acima), uma maneira é que o chamador reserve espaço e informe a function para usá-lo:

 void fn(int x[], int n) { for (int i = 0; i < n; ++i) x[i] = n; } void caller() { // local space on the stack - destroyed when caller() returns int x[10]; fn(x, sizeof x / sizeof x[0]); // or, use the heap, lives until delete[](p) called... int* p = new int[10]; fn(p, 10); } 

Outra opção é envolver o array em uma estrutura, que - ao contrário dos arrays brutos - é legal para retornar por valor de uma function:

 struct X { int x[10]; }; X fn() { X x; xx[0] = 10; // ... return x; } void caller() { X x = fn(); } 

Começando com o acima, se você está preso usando C ++ 03 você pode querer generalizá-lo em algo mais próximo do C ++ 11 std::array :

 template  struct array { T& operator[](size_t n) { return x[n]; } const T& operator[](size_t n) const { return x[n]; } size_t size() const { return N; } // iterators, constructors etc.... private: T x[N]; }; 

Outra opção é ter a function chamada alocar memory no heap:

 int* fn() { int* p = new int[2]; p[0] = 0; p[1] = 1; return p; } void caller() { int* p = fn(); // use p... delete[] p; } 

Para ajudar a simplificar o gerenciamento de objects heap, muitos programadores C ++ usam "pointers inteligentes" que garantem a exclusão quando o (s) ponteiro (s) do object deixam seus escopos. Com o C ++ 11:

 std::shared_ptr p(new int[2], [](int* p) { delete[] p; } ); std::unique_ptr p(new int[3]); 

Se você está preso em C ++ 03, a melhor opção é ver se a biblioteca de boost está disponível em sua máquina: ela fornece boost::shared_array .

Outra opção é ter uma memory estática reservada por fn() , embora isso NÃO seja THREAD SAFE, e significa que cada chamada para fn() sobrescreve os dados vistos por qualquer pessoa que mantiver pointers de chamadas anteriores. Dito isto, pode ser conveniente (e rápido) para um código simples de um único segmento.

 int* fn(int n) { static int x[2]; // clobbered by each call to fn() x[0] = n; x[1] = n + 1; return x; // every call to fn() returns a pointer to the same static x memory } void caller() { int* p = fn(3); // use p, hoping no other thread calls fn() meanwhile and clobbers the values... // no clean up necessary... } 

Não é possível devolver uma matriz de uma function C ++. 8.3.5 [dcl.fct] / 6:

Funções não devem ter um tipo de retorno do tipo matriz ou function […]

As alternativas mais comumente escolhidas são retornar um valor do tipo de class onde essa class contém uma matriz, por exemplo

 struct ArrayHolder { int array[10]; }; ArrayHolder test(); 

Ou para retornar um ponteiro para o primeiro elemento de uma matriz alocada estaticamente ou dinamicamente, a documentação deve indicar ao usuário se ele precisa (e, em caso afirmativo, como deve) desalocar a matriz para a qual o ponteiro retornado aponta.

Por exemplo

 int* test2() { return new int[10]; } int* test3() { static int array[10]; return array; } 

Embora seja possível retornar uma referência ou um ponteiro para uma matriz, é extremamente raro, pois é uma syntax mais complexa sem nenhuma vantagem prática sobre qualquer um dos methods acima.

 int (&test4())[10] { static int array[10]; return array; } int (*test5())[10] { static int array[10]; return &array; } 

Bem, se você quiser retornar sua matriz de uma function, você deve certificar-se de que os valores não são armazenados na pilha, pois eles desaparecerão quando você deixar a function.

Portanto, torne sua matriz estática ou aloque a memory (ou passe-a, mas sua tentativa inicial é com um parâmetro void). Para o seu método eu definiria assim:

 int *gnabber(){ static int foo[] = {1,2,3} return foo; } 

“como posso retornar um array em um método c ++ e como devo declará-lo? int [] test (void); ??”

 template  class Array { X *m_data; int m_size; public: // there constructor, destructor, some methods int Get(X* &_null_pointer) { if(!_null_pointer) { _null_pointer = new X [m_size]; memcpy(_null_pointer, m_data, m_size * sizeof(X)); return m_size; } return 0; } }; 

apenas para int

 class IntArray { int *m_data; int m_size; public: // there constructor, destructor, some methods int Get(int* &_null_pointer) { if(!_null_pointer) { _null_pointer = new int [m_size]; memcpy(_null_pointer, m_data, m_size * sizeof(int)); return m_size; } return 0; } }; 

exemplo

 Array array; float *n_data = NULL; int data_size; if(data_size = array.Get(n_data)) { // work with array } delete [] n_data; 

exemplo para int

 IntArray array; int *n_data = NULL; int data_size; if(data_size = array.Get(n_data)) { // work with array } delete [] n_data;