我该如何从一个方法中返回一个数组,以及如何声明这个数组?
int[] test(void); // ??
我该如何从一个方法中返回一个数组,以及如何声明这个数组?
int[] test(void); // ??
int* test();
然而,使用向量会更符合C++的风格:
std::vector< int > test();
编辑
我想澄清一些事情。既然您提到了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++,std::vector<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
}
更加易于操作和更安全。
std::vector
。 - Daniel Lidströmint* test();
是具有误导性的。 - CB Baileystd::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;
}
std::shared_ptr<int> p(new int[2], [](int* p) { delete[] p; } );
std::unique_ptr<int[]> p(new int[3]);
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...
}
new[] int(10)
是一个有效的新表达式。你是不是想说 new int[10]
? - CB Bailey在C++中,不可能从函数返回一个数组。根据8.3.5[dcl.fct]/6规定:
函数的返回类型不能是数组或函数[...]
最常见的替代方案是返回一个类类型的值,其中该类包含一个数组,例如:
struct ArrayHolder
{
int array[10];
};
ArrayHolder test();
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;
}
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;
}
};
只适用于整数
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;
std::array
或std::vector
,而不是 C 风格数组。 - Jesper Juhl