C++函数调用到二维数组

3

我在 County.h 类的构造函数中:

struct Country {
    Country(double**, int);
};

在主函数中,我有一个graph[Size][Size]数组,并且我想调用County的构造函数。

int main() {
    double graph[Size][Size];
    Country c(graph, 0);
}

但是它给我错误提示:no matching function for call to ‘County::County(double [22][22], int)’

为了解决这个问题,我可以做什么?


2
数组的数组不是指针的数组。 - molbdnilo
1
@JoeUrc 我怀疑将double重新解释为指针不会带来任何有用的结果。 - Quentin
@tobi303 因为嵌套向量很麻烦。 - Quentin
@Quentin,为什么它们是邪恶的?当涉及将它们传递或从函数返回时,C风格数组很麻烦,但嵌套向量有什么问题呢? - 463035818_is_not_a_number
@tobi303 避免使用 C 风格的数组是好的。然而,嵌套向量会带来另一组问题:它们的行可以隐式地改变长度,并且它们真正破坏缓存。不幸的是,标准库没有提供多维动态数组,但 Boost.MultiArray 很好。 - Quentin
显示剩余3条评论
2个回答

4

double [Size][Size]double**并不是完全相同的类型。这就是你的编译器不喜欢的原因。

更改你的构造函数原型或你声明数组的方式。但你不能直接将一个二维数组强制转换为指针。

struct Country {
    Country(double[Size][Size], int);
};

或者:

int main() {
    double** graph = new (double*)[Size];
    for (int i = 0; i < Size; ++i) {
        graph[i] = new double[Size];
    }
    Country c(graph, 0);

    // Don't forget to delete your graph then.
}

请注意,第一种方法要求您在代码开始执行之前就知道大小(例如,在宏中存储Size),但第二种方法的编写时间更长,您将不得不操作更多的RAM内存,如果不小心可能会导致错误。


我认为我创建了类似于你的第一个解决方案,但我没有给出大小。 - MaxDevelop
@Saif 如果在你的Country.h文件中,你编写了一个以double **参数为输入的构造函数,那么它与没有给出Size是完全不同的:这是一种不同的变量类型。在这里,一个有效的构造函数应该采用一个double [x][x],其中x是一个宏定义。 - Aracthor

1

另一种方法是将您的构造函数声明为模板,并通过(const)引用传递数组,

struct Country {
    template<size_t N>
    Country(double /*const*/ (&arr)[N][N], int);
};

以这种方式,模板将直接推断出数组的大小。当然,缺点是上述方法不能用于双指针。优点是编译器会强制检查类型,如果数组不是由double组成(在类型推导时不进行转换)或者不是方形的,则程序甚至无法编译。

1
这种方法的麻烦之处在于,它将几乎所有必须处理此数组的内容都链接到一个编译单元中。但是,是的,这似乎是C ++可以做到的最好的。在这方面,它明显不如C ... - cmaster - reinstate monica
@cmaster 我想这就是强制类型安全所要付出的代价。 - vsoftco
@cmaster 我必须说我对纯 C 不是很熟悉。那么你会像这样编写该函数: void f(int m,int n, int x[m] [n]) {} 并传递维数吗? (我认为您至少需要传递维数)。 问题是它将允许传递不同大小和类型的数组(至少在我的机器上,gcc 只会发出警告)。 - vsoftco
是的,那是基本想法。不幸的是,我必须认识到你是对的,gcc 不检查类型。我猜这可能是 gcc 的缺陷,而不是标准的缺陷,但我可能错了。理论上,可以做所有所需的类型检查(您不需要知道数组大小的值来断言从相同变量派生的两个数组类型是相同的),但它确实增加了相当多的编译器复杂性,并且 VLAs 不是最常用的功能。 - cmaster - reinstate monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接