数组指针、函数指针和尾置返回类型

/* 本文试着给出一些结论

* 1 就近原则,const在指针符后面时修饰指针本身,在指针符前面时修饰指针所指变量

* 2 指针化原则,任何的变量,你想定义它的指针的时候,只要在指针声明上多加个括号和指针符即可

* 3 还原原则,任何的指针,你想知道它指向的变量的类型时,只要把小括号和*号去掉即可

* 4 优先原则,当指针被小括号扩起来时,优先考虑它是指针,否则,它是数组

*

* 指针化原则和还原原则对数组和函数都是适用的。

* 以后如果想定义一个函数的指针,只要比函数声明时多加括号和星号即可

*

* 还要说一下对 typedef 的理解,typedef 和变量声明的格式是一样的

* 只不过 typedef 声明了一个类型而已

*

* 如果因为返回类型太复杂而无法显式声明一个函数指针,那你可以用decltype来查询函数的类型

*

* 本文还要说明的知识点是:

* 1 函数如何返回数组指针

* 2 尾置返回类型

* 3 typedef

* 4 decltype

*/

#include <algorithm>

/*
 */
void ptr_description()
{
    int a[10]; // 整型数组, a的类型是 int*, &a的类型是 int (*)[10]
    int *p1 = a; // 整型指针指向整型数组

    // 看看符合指针化原则吗?
    // 同时优先原则也起作用,它是个指针
    int (*p2)[10] = &a; //数组指针, 所以初始化时记得要用地址符取地址

    // 根据优先原则来判断,它是数组
    int *pp1[10]; // 指针数组
    pp1[0] = a;

    int b[5];

    // 就近原则
    const int *cp1 = a; // 指向只读数组的指针
    cp1 = b;

    // 就近原则
    int *const cp2 = a; // 指向数组的只读指针
    *(cp2 + 2) = 3;

    // 错误: cannot convert 'int*' to 'int (*)[10]' in initialization
    // int (*ep2)[10] = a;

    // 错误: assignment of read-only location '*(cp1 + 8u)'
    // *(cp1 + 2) = 3;

    // 错误: assignment of read-only variable 'cp2'
    // cp2 = b;
}

/* arithmetic_sequence是一个返回数组指针的函数
 * 函数的声明形式是 Type (*function(parameter_list))[dimension]
 * 我们来逐层理解该声明的含义
 *    arithmetic_sequence(int i) 决定了函数名和参数列表
 *    (*arithmetic_sequence(int i)) *号决定了函数返回的是一个指针
 *    int (*arithmetic_sequence(int i))[10] int 和 10 决定了数组的元素类型和长度
 * 函数的声明也遵循指针化原则和优先原则
 */
int (*arithmetic_sequence(int i))[10]
{
    static int array[10];

    std::transform(array, array + 10, array, [&] (int) {return i++;});

    return &array;
}

// 这是一种尾置返回类型的声明格式
// 对于返回类型比较复杂的函数更有效,可以直观的看出返回类型
auto arithmetic_sequence1(int i) -> int (*)[10]
{
    static int array[10];

    std::transform(array, array + 10, array, [&] (int) {return i++;});

    return &array;
}

int main(int argc, char *argv[])
{
    // 指针化原则和还原原则
    int (*(*func)(int i))[10];
    func = arithmetic_sequence;

    // 正如预期,输出14
    printf("%d\n", (*func(5))[9]);

    func = arithmetic_sequence1;

    // 正如预期,输出13
    printf("%d\n", (*func(5))[8]);

    typedef int (*(*Func)(int i))[10];
    Func func1= arithmetic_sequence;

    // 正如预期,输出12
    printf("%d\n", (*func1(5))[7]);

    decltype(arithmetic_sequence) *func2 = arithmetic_sequence;

    // 正如预期,输出11
    printf("%d\n", (*func2(5))[6]);

    return 0;
}

 

posted on 2016-11-15 16:52  ddev  阅读(637)  评论(0编辑  收藏  举报