我的问题是如果函数返回一个数组可能会出错?我们可以使用这样的功能吗?
答案 0 :(得分:1)
C ++不允许函数将数组类型作为prvalue返回;但是,xvalues和左值很好:
using T = int[10];
T & foo(); // OK, returns lvalue
T && foo(); // OK, returns xvalue
T foo(); // Error, not allowed
同样是函数类型(尽管在这种情况下函数调用表达式的结果总是左值)。见[dcl.fct] / 10:
函数不应具有类型数组或函数的返回类型,尽管它们可能具有类型指针的返回类型或对此类事物的引用。
类似地,数组和函数类型不能是函数参数类型(但是对它们的引用可以),但是具有这种类型的函数参数声明的含义被调整为"指向{数组元素类型,函数类型的指针}"
答案 1 :(得分:1)
在C ++和C函数中都没有返回类型的数组。数组没有复制构造函数或复制赋值运算符。
然而,在C ++中,您可以返回对数组的引用。
考虑以下示例
#include <iostream>
#include <numeric>
const size_t N = 10;
int ( & init( int ( &a )[N], int initial ) )[N]
{
std::iota( a, a + N, initial );
return a;
}
std::ostream & print( const int ( &a )[N], std::ostream &os = std::cout )
{
for ( int x : a ) os << x << ' ';
return os;
}
int main()
{
int a[N];
print( init( a, 0 ) ) << std::endl;
print( init( a, 10 ) ) << std::endl;
return 0;
}
输出
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
但是,您可能不会将引用或指针(指向第一个元素)返回到函数的本地数组。在这种情况下,程序将具有未定义的行为。
但是你可以使用数组std::array
的标准包装器并从函数返回它。
这是一个例子
#include <iostream>
#include <numeric>
#include <array>
const size_t N = 10;
std::array<int, N> init(int initial = 0 )
{
std::array<int, N> a;
std::iota( a.begin(), a.end(), initial );
return a;
}
std::ostream & print( const std::array<int, N> &a, std::ostream &os = std::cout )
{
for ( int x : a ) os << x << ' ';
return os;
}
int main()
{
std::array<int, N> a;
a = init();
print( a ) << std::endl;
a = init( 10 );
print( a ) << std::endl;
return 0;
}
程序输出与上面相同
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
答案 2 :(得分:0)
函数不能直接返回数组,因为不能简单地复制或移动数组。
它可以返回指向数组开头的指针。如果函数返回后数组继续存在,这很好。但是如果数组是一个局部自动变量,那将会出现可怕的错误,因为它会在函数返回时被销毁,而指针会悬空。试图访问数组的残余将给出未定义的行为。
因为你问了一个例子:
int * bogus() {
int array[] = {1,2,3,4,5};
return array; // Whoops! array is destroyed here
}
int * p = bogus();
assert(p[2] == 3); // BOOM! undefined behaviour
如果数组有一个小的固定大小,你可以将它包装在一个类中以返回它的副本;标准库为此提供了std::array
。
如果你需要动态分配数组(因为它很大,或者只在运行时知道大小),那么std::vector
就是你的朋友。
答案 3 :(得分:0)
停止使用这些旧东西。开始使用 STL 。您始终可以将vector or string
传递到function parameters
,并始终将其作为return
值从函数中获取。
答案 4 :(得分:0)
正如Mike Seymour所说,函数不能返回一个数组,只能指向它的第一个元素。
本身完全正确,但如果误用可能会导致错误。可能出现的一些问题:
返回一个指向自动数组的指针:如果函数返回= if将被销毁UB当您尝试访问它时
int * arr() {
int arr[10]; // automatic array
...
return arr; // WRONG ! UB when accessed from caller ...
}
返回一个指向动态分配数组的指针:很好但调用者必须在不再使用它时释放它或者你会有内存泄漏
int * arr() {
int *arr = new int[10]; // automatic array
...
return arr; MUST be freed by caller ...
}
for (int i=0; i<5, i++) {
int *a = arr();
... // use a
} // no delete[] a in loop => memory leak !
返回一个指向静态数组的指针:很好但不应该在多线程上下文中使用
int * arr() {
static int arr[10]; // automatic array
...
return arr; // as arr is static it will persist after function returns
}
线程a:
int *a = arr();
主题b:
int *a = arr();
两个线程现在通过a
指针共享相同的数组,如果数组不是只读的话,通常不期望。
正如我所说,返回指向非自动数组的指针是可以的。必须谨慎使用它,因为这通常会导致问题。