2010-11-24 4 views

ответ

54

int* test();

, но это будет "более C++", чтобы использовать векторы:

std::vector<int> test();

EDIT
Я поясню некоторую точку. Поскольку вы упомянули C++, я поеду с операторами new[] и delete[], но это то же самое с malloc/free.

В первом случае, вы будете писать что-то вроде:

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

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

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

Лучше подпись будет такой:

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

И ваш клиентский код будет теперь:

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. 

Поскольку это C++, `станд :: вектор < T> является широко используемым решением:

std::vector<int> test() { 
    std::vector<int> vector(10); 
    return vector; 
} 

Теперь вам не нужно звонить delete[], так как он будет обработан объектом, и вы можете спокойно перебирать его:

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

, который легче и безопаснее.

+2

Я бы с возвратом `зЬй :: VECTOR`. – 2010-11-24 08:08:54

+8

Лично я считаю, что ответ `int * test();` на вопрос «как вернуть массив в метод C++?» [Sic] вводит в заблуждение, если вы не объясните, что он фактически не возвращает массив но указатель. – 2010-11-24 09:53:41

2

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

Так что либо сделайте свой массив статическим, либо выделите память (или передайте ее, но ваша первоначальная попытка - с параметром void). Для вашего метода я бы определил это так:

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

, как я могу вернуть массив в методе C++ и как я должен объявить его? int [] test (void); ??

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

  • std::vector<>, который растет динамически, однако многие элементы, которые вы сталкиваетесь во время выполнения, или

  • std::array<> (введен с C++ 11), который всегда хранит число элементов, указанный во время компиляции,

... как управлять памятью для вас, обеспечивая правильное поведение и упрощая значительно:

std::vector<int> fn() 
{ 
    std::vector<int> x; 
    x.push_back(10); 
    return x; 
} 

std::array<int, 2> fn2() // C++11 
{ 
    return {3, 4}; 
} 

void caller() 
{ 
    std::vector<int> a = fn(); 
    const std::vector<int>& b = fn(); // extend lifetime but read-only 
             // b valid until scope exit/return 

    std::array<int, 2> c = fn2(); 
    const std::array<int, 2>& d = fn2(); 
} 

Практика создания ссылки на возвращаемые данные иногда позволяет избежать копирования, но обычно вы можете просто полагаться на Оптимизацию возвращаемого значения или - на vector, но не на array - перемещать семантику (введено с C++ 11) ,

Если вы действительно хотите использовать встроенный массив (в отличие от стандартного класса библиотеки под названием array упоминалось выше), один из способов для вызывающего абонента, чтобы зарезервировать место и указать функции использовать:

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); 
} 

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

struct X 
{ 
    int x[10]; 
}; 

X fn() 
{ 
    X x; 
    x.x[0] = 10; 
    // ... 
    return x; 
} 

void caller() 
{ 
    X x = fn(); 
} 

Начиная с вышеизложенным, если вы застряли с помощью C++ 03 вы можете обобщить его в чем-то ближе к C++ 11 std::array:

template <typename T, size_t N> 
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]; 
}; 

Другим вариантом является вызываемая функция выделяет память в куче:

int* fn() 
{ 
    int* p = new int[2]; 
    p[0] = 0; 
    p[1] = 1; 
    return p; 
} 

void caller() 
{ 
    int* p = fn(); 
    // use p... 
    delete[] p; 
} 

К помогите упростить управление объектами кучи, многие программисты на С ++ используют «умные указатели», которые обеспечивают удаление, когда указатель (ы) на объект покидают свои области. С C++ 11:

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

Если вы застряли на C++ 03, лучший вариант, чтобы увидеть, если библиотека бустер доступны на вашей машине: она обеспечивает boost::shared_array.

Еще одна опция - иметь некоторую статическую память, зарезервированную fn(), хотя это НЕ БЕЗОПАСНАЯ БЕЗОПАСНОСТЬ, и означает, что каждый вызов fn() перезаписывает данные, которые видят все, кто удерживает указатели от предыдущих вызовов. Тем не менее, это может быть удобно (и быстро) для простого однопоточного кода.

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... 
} 
9

Невозможно вернуть массив из функции C++. 8.3.5 [dcl.fct]/6:

Функции не должны иметь тип возвращаемого массива типа или функции [...]

Чаще всего выбранные альтернативы должны возвращать значение тип класса, в котором этот класс содержит массив, например

struct ArrayHolder 
{ 
    int array[10]; 
}; 

ArrayHolder test(); 

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

E.g.

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

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

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

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

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

"как я может возвращать массив в C++ метод и как я должен объявить его INT [] тест (недействительными);? ??"

template <class X> 
    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; 
    } 
}; 

только для 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; 
    } 
}; 

например

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

delete [] n_data; 

пример для Int

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

delete [] n_data; 
Смежные вопросы