как я могу вернуть массив в методе 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();
}
Практика создания const
ссылки на возвращаемые данные иногда позволяет избежать копирования, но обычно вы можете просто положиться на Оптимизацию возвращаемого значения или - для 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: она обеспечивает 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...
}