C++ 如何从函数返回数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4264304/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to return an array from a function?
提问by ewggwegw
How can I return an array from a method, and how must I declare it?
如何从方法返回一个数组,我必须如何声明它?
int[] test(void); // ??
回答by Simone
int* test();
int* test();
but it would be "more C++" to use vectors:
但使用向量将是“更多的 C++”:
std::vector< int > test();
std::vector< int > test();
EDIT
I'll clarify some point. Since you mentioned C++, I'll go with new[]
and delete[]
operators, but it's the same with malloc/free.
编辑
我会澄清一些观点。既然你提到了 C++,我就用new[]
anddelete[]
运算符,但是 malloc/free 也是一样。
In the first case, you'll write something like:
在第一种情况下,您将编写如下内容:
int* test() {
return new int[size_needed];
}
but it's not a nice idea because your function's client doesn't really know the size of the array you are returning, although the client can safely deallocate it with a call to delete[]
.
但这不是一个好主意,因为您的函数的客户端并不真正知道您返回的数组的大小,尽管客户端可以通过调用delete[]
.
int* theArray = test();
for (size_t i; i < ???; ++i) { // I don't know what is the array size!
// ...
}
delete[] theArray; // ok.
A better signature would be this one:
更好的签名是这个:
int* test(size_t& arraySize) {
array_size = 10;
return new int[array_size];
}
And your client code would now be:
你的客户端代码现在是:
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.
Since this is C++, std::vector<T>
is a widely-used solution:
由于这是 C++,因此std::vector<T>
是一种广泛使用的解决方案:
std::vector<int> test() {
std::vector<int> vector(10);
return vector;
}
Now you don't have to call delete[]
, since it will be handled by the object, and you can safely iterate it with:
现在您不必调用delete[]
,因为它将由对象处理,您可以安全地迭代它:
std::vector<int> v = test();
std::vector<int>::iterator it = v.begin();
for (; it != v.end(); ++it) {
// do your things
}
which is easier and safer.
这更容易和更安全。
回答by Tony Delroy
how can i return a array in a c++ method and how must i declare it? int[] test(void); ??
我如何在 C++ 方法中返回一个数组,我必须如何声明它?int[] 测试(无效);??
This sounds like a simple question, but in C++ you have quite a few options. Firstly, you should prefer...
这听起来像是一个简单的问题,但在 C++ 中,您有很多选择。首先,你应该更喜欢...
std::vector<>
, which grows dynamically to however many elements you encounter at runtime, orstd::array<>
(introduced with C++11), which always stores a number of elements specified at compile time,
std::vector<>
,它会动态增长到您在运行时遇到的许多元素,或者std::array<>
(在 C++11 中引入),它总是存储在编译时指定的多个元素,
...as they manage memory for you, ensuring correct behaviour and simplifying things considerably:
...因为他们为您管理内存,确保正确的行为并大大简化事情:
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();
}
The practice of creating a const
reference to the returned data can sometimes avoid a copy, but normally you can just rely on Return Value Optimisation, or - for vector
but not array
- move semantics (introduced with C++11).
创建const
对返回数据的引用的做法有时可以避免复制,但通常您可以只依赖返回值优化,或者 - forvector
但不是array
- 移动语义(在 C++11 中引入)。
If you really want to use an inbuiltarray (as distinct from the Standard library class called array
mentioned above), one way is for the caller to reserve space and tell the function to use it:
如果您真的想使用内置数组(与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);
}
Another option is to wrap the array in a structure, which - unlike raw arrays - are legal to return by value from a function:
另一种选择是将数组包装在一个结构中,与原始数组不同,该结构可以合法地从函数中按值返回:
struct X
{
int x[10];
};
X fn()
{
X x;
x.x[0] = 10;
// ...
return x;
}
void caller()
{
X x = fn();
}
Starting with the above, if you're stuck using C++03 you might want to generalise it into something closer to the C++11 std::array
:
从上述开始,如果您坚持使用 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];
};
Another option is to have the called function allocate memory on the 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;
}
To help simplify the management of heap objects, many C++ programmers use "smart pointers" that ensure deletion when the pointer(s) to the object leave their scopes. With C++11:
为了帮助简化堆对象的管理,许多 C++ 程序员使用“智能指针”来确保在指向对象的指针离开其作用域时删除。使用 C++11:
std::shared_ptr<int> p(new int[2], [](int* p) { delete[] p; } );
std::unique_ptr<int[]> p(new int[3]);
If you're stuck on C++03, the best option is to see if the boost library is available on your machine: it provides boost::shared_array
.
如果您坚持使用 C++03,最好的选择是查看您的机器上是否有 boost 库:它提供boost::shared_array
.
Yet another option is to have some static memory reserved by fn()
, though this is NOT THREAD SAFE, and means each call to fn()
overwrites the data seen by anyone keeping pointers from previous calls. That said, it can be convenient (and fast) for simple single-threaded code.
另一种选择是保留一些静态内存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...
}
回答by CB Bailey
It is not possible to return an array from a C++ function. 8.3.5[dcl.fct]/6:
不可能从 C++ 函数返回数组。8.3.5[dcl.fct]/6:
Functions shall not have a return type of type array or function[...]
函数不应具有数组或函数类型的返回类型[...]
Most commonly chosen alternatives are to return a value of class type where that class contains an array, e.g.
最常用的替代方法是返回一个类类型的值,其中该类包含一个数组,例如
struct ArrayHolder
{
int array[10];
};
ArrayHolder test();
Or to return a pointer to the first element of a statically or dynamically allocated array, the documentation must indicate to the user whether he needs to (and if so how he should) deallocate the array that the returned pointer points to.
或者要返回一个指向静态或动态分配的数组的第一个元素的指针,文档必须向用户指明他是否需要(如果需要,他应该如何)释放返回的指针指向的数组。
E.g.
例如
int* test2()
{
return new int[10];
}
int* test3()
{
static int array[10];
return array;
}
While it is possible to return a reference or a pointer to an array, it's exceedingly rare as it is a more complex syntax with no practical advantage over any of the above methods.
虽然可以返回一个引用或指向数组的指针,但这种情况非常罕见,因为它是一种更复杂的语法,与上述任何一种方法相比都没有实际优势。
int (&test4())[10]
{
static int array[10];
return array;
}
int (*test5())[10]
{
static int array[10];
return &array;
}
回答by Mark
Well if you want to return your array from a function you must make sure that the values are not stored on the stack as they will be gone when you leave the function.
好吧,如果你想从一个函数中返回你的数组,你必须确保这些值没有存储在堆栈中,因为当你离开函数时它们会消失。
So either make your array static or allocate the memory (or pass it in but your initial attempt is with a void parameter). For your method I would define it like this:
因此,要么将数组设为静态,要么分配内存(或将其传入,但您的初始尝试是使用 void 参数)。对于您的方法,我会这样定义它:
int *gnabber(){
static int foo[] = {1,2,3}
return foo;
}
回答by ksdarkonix
"how can i return a array in a c++ method and how must i declare it? int[] test(void); ??"
“我如何在 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;
}
};
just for int
只是为了 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;
}
};
example
例子
Array<float> array;
float *n_data = NULL;
int data_size;
if(data_size = array.Get(n_data))
{ // work with array }
delete [] n_data;
example for int
以 int 为例
IntArray array;
int *n_data = NULL;
int data_size;
if(data_size = array.Get(n_data))
{ // work with array }
delete [] n_data;