返回指向静态变量的指针并没有错。只是必须正确声明返回类型。如果您尝试重现声明的含义以及编译器相应地尝试执行的操作,那是有道理的。考虑声明static string flow[23][2];。它声明了 23 行字符串,每行有 2 个元素。如果您将其视为一维数组,它会有所帮助。数组元素恰好是数组,但现在这并不重要(但我们会回到它)。从这个角度来看,数组只有 23 个元素,每个元素的大小为 2 个字符串。与所有数组一样,元素(这里:2 个字符串的数组)只是在内存中排列。
像任何数组一样,flow 在大多数情况下都会衰减为指向其第一个元素的指针。递增该指针将指向下一个元素,即第二行。在数值上,编译器必须将 2*sizeof(string) 添加到 flow 的地址,以便计算 flow 的下一个元素的地址,即 flow[1]。 (它直接在 flow[0] 后面。这里没有魔法。)
现在如果你声明string **flowpp,flowpp 已经是一个指针,不需要衰减。如果我们认为它指向数组中的第一个元素,那么元素的类型是什么?果然:纯指针。递增 flowpp 将让它指向下一个元素。我的指针有 4 个字节大,因此将 just 4 数字添加到 flowpp 就足以访问 flowpp 的下一个元素。与需要添加到流中的内容相比(请记住,2*sizeof(string)),这是完全不同的。 编译器根据指针指向的内容计算元素的偏移量!这两种情况有很大不同。
那么可以你的函数返回什么?当你返回它时,流量会衰减到什么程度?它衰减为指向其第一个元素的指针。元素是两个字符串的数组。它必须是 string xxx[2],其中 xxx 是一个指针:因此是 string (*p)[2]。如果指针实际上是由函数返回的,我们有一个函数调用而不是普通的 p,所以它是(*f())[2]。
这是一个完整的例子:
#include<iostream>
using namespace std;
const int numFlowElems = 3, numArrElems = 2;
/** @return a pointer to the first element of a static array
of string[numArrElems]s.
*/
string (*flowFile())[numArrElems]
{ // init so that we see something below.
static string flow[numFlowElems][numArrElems]
= {{"1","2"},
{"3","4"},
{"5","6"}
};
// your function code ...
return flow;
}
int main()
{
// array decays to ptr, like usual. Ptr elems are string[numArrElems].
// ptrToArr is a pointer to arrays of two strings.
string (*ptrToArr)[numArrElems] = flowFile();
for( int flowInd= 0; flowInd<numFlowElems; ++flowInd )
{
for(int strInd = 0; strInd<numArrElems; ++strInd)
{
cout << ptrToArr[flowInd][strInd] << ' ';
}
cout << endl;
}
return 0;
}
你如何解析string (*flowFile())[numArrElems]?我需要两次尝试才能使声明正确,如果这是任何安慰的话。关键是在 C 和 C++ 中(不是在 C# 中,请注意!)声明具有表达式的形状。
您可以从内到外进行:flowFile() 是一个函数。结果被取消引用,因为函数调用的优先级高于星号:*flowFile() 是取消引用的结果。显然,结果是一个大小为 numArrElems 的数组,其中的元素是字符串。
你可以在外面做:(*flowFile())[numArrElems] 的结果被声明为一个字符串。 (*flowFile()) 是一个包含 numArrElems 元素的字符串数组。显然,flowFile() 必须取消引用才能获得该数组,以便 flowfile 是一个返回指向 numArrElems 字符串数组的指针的函数。确实如此!它返回 flow 的第一个元素,也就是一个字符串数组。
向量的向量可能确实更容易;如果你想保留语义,你应该传递引用,正如其他人提到的那样:毕竟,原始程序中的所有函数都将在同一个静态数组上运行。如果您按值传递向量,情况将不再如此。但是,这实际上可能是有益的。