如何从函数返回数组?
我怎样才能从一个方法返回一个数组,我怎样才能声明它呢?
int[] test(void); // ??
int* test();
但是使用向量会是“更多的C ++”:
std::vector< int > test();
编辑
我会澄清一点。 既然你提到了C ++,我将使用new[]
和delete[]
运算符,但是和malloc / free一样。
在第一种情况下,你会写如下的东西:
int* test() { return new int[size_needed]; }
但是这不是一个好主意,因为你的函数的客户端并不知道你正在返回的数组的大小,尽pipe客户端可以通过调用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 ++,`std :: vector <T>是一个广泛使用的解决scheme:
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 }
这更简单,更安全。
我怎样才能返回一个数组在c + +方法,我该如何申报呢? int [] test(void); ??
这听起来像一个简单的问题,但在C ++中,你有很多select。 首先,你应该更喜欢…
-
std::vector<>
,它dynamic地增长到在运行时遇到的许多元素,或者 -
std::array<>
(在C ++ 11中引入),它总是存储编译时指定的许多元素,
…为他们pipe理记忆,确保正确的行为和相当简化的事情:
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(); }
创build一个返回数据的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); }
另一个select是将数组包装在一个结构中,与原始数组不同,这个结构是合法的,可以从函数返回值:
struct X { int x[10]; }; X fn() { X x; xx[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]; };
另一个select是让被调用的函数在堆上分配内存:
int* fn() { int* p = new int[2]; p[0] = 0; p[1] = 1; return p; } void caller() { int* p = fn(); // use p... delete[] p; }
为了帮助简化堆对象的pipe理,许多C ++程序员使用“智能指针”来确保当指向对象的指针离开它们的作用域时被删除。 用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
。
另外一个select是使用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... }
从C ++函数中返回数组是不可能的。 8.3.5 [dcl.fct] / 6:
函数不应该有返回types的数组或函数[…]
最常用的select是返回一个类types的值,其中该类包含一个数组,例如
struct ArrayHolder { int array[10]; }; ArrayHolder test();
或者返回一个指向静态或dynamic分配数组的第一个元素的指针,文档必须指示用户他是否需要(以及如何如何)解除分配返回的指针指向的数组。
例如
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; }
那么如果你想从一个函数返回你的数组,你必须确保这些值不会被存储在堆栈上,因为当你离开函数的时候它们将会消失。
所以要么让你的数组是静态的,要么分配内存(或者把它传入,但是你最初的尝试是用一个void参数)。 对于你的方法,我会这样定义它:
int *gnabber(){ static int foo[] = {1,2,3} return foo; }
“我怎样才能返回一个数组在c + +方法,我该如何声明呢?int [] test(void); ??”
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;