为什么我不能使用std :: begin / std :: end和int(* p)[3]而我可以使用int(& p)[3]?

时间:2018-05-15 02:49:07

标签: c++

这有效:

void foo(int (&a)[3]) {
    auto ibegin = begin(a);
    auto ebegin = end(a);
}

虽然这不是:

void foo(int (*a)[3]) {
    auto ibegin = begin(a);
    auto ebegin = end(a);
}

我认为int (&a)[3]int (*a)[3]具有相同的含义!

5 个答案:

答案 0 :(得分:8)

您的代码类似于:

void foo(vector<int>& a) {
    auto ibegin = begin(a);
    auto ebegin = end(a);
}

void foo(vector<int>* a) {
    auto ibegin = begin(a);
    auto ebegin = end(a);
}

第一个起作用,第二个起作用的原因与它在int (&a)[3]上的作用相同,并且不在int (*a)[3]上。当您使用指向集合而不是引用的指针时,您需要在将它们传递给标准库begin / end时取消引用它们。

void foo(vector<int>* a) {
    auto ibegin = begin(*a);
    auto ebegin = end(*a);
}

void foo(int (*a)[3]) {
    auto ibegin = begin(*a);
    auto ebegin = end(*a);
}

答案 1 :(得分:7)

  

我认为let jsonString = String(data: responseData, encoding: .utf8)int (&a)[3]具有相同的含义!

绝对不是。 int (*a)[3]声明对数组的引用,int (&a)[3]声明指向数组的指针。对于int (*a)[3]的引用和int的指针不同,大多数情况都不同。 (虽然涉及C风格的数组时,自动数组到指针的转换有时会使事情变得复杂。)

答案 2 :(得分:4)

  

我认为int(&amp; a)[3]和int(* a)[3]具有相同的含义!

没有!第一个是对数组的引用,第二个是指向数组的指针。

在C ++ 14 std::beginstd::end中定义为:

template<class T, std::size_t N> 
constexpr T* begin(T (&array)[N]) noexcept;

template<class T, std::size_t N> 
constexpr T* end(T (&array)[N]) noexcept;

显然,这些函数引用了一个数组,而不是一个指针。

答案 3 :(得分:4)

你可能理解函数重载的区别,其中三个分别是对数组的引用,指向数组的指针和指针数组。所以他们没有相同的含义。

#include <iostream>

void foo(int (&a)[3]) {
    std::cout << "(&a)[3]" << std::endl;
}

void foo(int (*a)[3]) { 
    std::cout << "(*a)[3]" << std::endl;
}

void foo(int *a[3]) {
    std::cout << "*a[3]" << std::endl;
}

int main() {
    int m[3];
    int *n[3] = {m + 0, m + 1, m + 2};
    foo(m);       // (&a)[3]
    foo(&m);      // (*a)[3]
    foo(n);       // *a[3]
}

答案 4 :(得分:1)

&符号获取指针的位置(&amp; a)您获得数组中位置0的a地址。

*a获取存储在[0]的值时,这称为取消引用指针。例如:

int * a = {0,1,2};

&a[0] //gets value of the memory pointer of a[0], maybe 0xff123
*a[0] //dereferences the pointer at [0] in this gets case '0'.

要更全面地了解指针,我会查看:What does "dereferencing" a pointer mean?