参数列表中char [N]和char(&)[N]之间的差异

时间:2016-04-16 09:11:41

标签: c++ c++11

以下代码无法编译:

ParseGeoPoint.getCurrentLocationInBackground(10000, new LocationCallback() {
    @Override
    public void done(ParseGeoPoint geoPoint, ParseException e) {

        if (e!=null)
        Print("location not found " + e.getLocalizedMessage());
        else
        {
            Print("location  found ");
        }
    }
});

如果我将template <int N> void f(char[N]) {} int main() { char buf[10]; f(buf); } 更改为char[N],则可行。那么它们之间有什么区别呢?

3 个答案:

答案 0 :(得分:7)

你被C语言的向后兼容性所困扰。当你声明一个像:

这样的函数时
int f(char c[10]);

声明一个参数类型为char *的函数。编译器为您解析参数类型。问题是:

int f(char c[5]);

声明相同的函数。这就是C的工作方式,C ++保留了它的兼容性。

int f(char (&c)[10]);

声明一个函数,其参数类型为“对char的数组(长度为10)的引用”。 C没有引用,因此不需要保持向后兼容性。

int f(char (&c)[5]);

使用不同的参数类型声明不同的函数。

答案 1 :(得分:2)

显然,您知道char [N]是一个数组,而char (&)[N]是对char [N]的引用。

c样式数组在按值作为参数传递时是特殊的。数组本身没有传递,但引用是。

这种“魔力”是c ++从C演变的历史副作用。

按值传递数组这些天我们使用std::array<char, N>来封装c风格的数组。

请注意char (&)[N]被视为文字类型,因此可以传递给constexpr上下文中的constexpr函数。

答案 2 :(得分:2)

我认为事件的顺序是

  • 编译器 不会查找正确的char[10]函数,因为该语言不支持将数组作为值传递。
  • 编译器会查找一个带有引用char[10] 的函数(并且找不到任何函数)。
  • 编译器查找一个函数,该函数带有指向char的指针,这是在称为类型调整之后的实际参数类型,并且没有找到任何

最后一点很有意思,因为模板函数f实际上确实带有一个指向char 的指针,正如其他海报所解释的那样:声明中的索引是多余的,并且在函数声明中f(char p[]) p不是类型数组,而是类型指向char的指针。请注意,这与其他地方的声明(不作为函数参数)不同,其中p将是一个数组,尽管不完整。

编译器无法实例化函数模板的原因并不是它的参数类型错误:它会在参数类型调整后匹配。原因很简单,它无法从参数中推断出模板参数N毕竟,对于每个N,都会有不同的f:哪一个应该编译器采取??实际论证buf已被&#34;调整后#34;对于指向其第一个元素的指针,参数中的长度信息将丢失。 (是的,编译器是愚蠢的。)

当您将函数声明为对数组的引用时,保留了长度信息。

另一种可能性是简单地实例化模板函数:

f<10>(buf);有效。