zoukankan      html  css  js  c++  java
  • 第6章 函数

    6.1 函数基础

    函数包括:返回类型、函数名称、形参列表、函数体

    函数调用:①用实参初始化形参;②控制权交给被调函数。
    return语句:①返回return语句的值;②控制权转移到主调函数。

    warming

    函数的返回类型不能是数组类型或者函数类型,但可以是指向数组和函数的指针。

    函数体内定义的自动对象,在函数结束后被销毁。
    函数体内定义的静态对象,在程序中只定义一次。

    函数声明也叫函数原型,一般在头文件中,不含有函数体。

    6.2 参数传递

    函数调用时,都会重新创建形参,并使用实参初始化形参。

    值传递和指针传递,都是将实参内存对应的数据,拷贝到形参对应的内存中。

    使用引用传递,是将形参绑定到初始化它的对象。(个人认为是指针传递的一个便捷写法,是一个语法糖)

    noting

    尽量使用引用,从而避免拷贝。如果函数中不修改实参,应该使用const限定。

    使用引用,还可以通过参数,返回函数中的内容。

    数组形参

    数组:①不允许拷贝;②使用数组名,通常会转换成指针。

    //以下定义等价,编译器忽略数组长度
    //定义成const,不能通过指针修改数组值,若需要修改,不适用const
    void print(const int*);
    void pirnt(const int[]);
    void print(const int[10]);
    
    //通常需要指明数组大小,或者结束标记
    //如果是C字符串,可以通过最后位的''判断结束
    void print(const int *beg, const int *end);
    void print const int ia[], const size_t size);
    
    //数组引用形参,维度是类型的一部分
    //这一做法可以使用sizeof判断数组占用的字节数
    //这一做法也限定了,只能使用大小为10的数组
    void print(int (&arr)[10]);

    多维数组:

    //matrix指向数组的首元素,此元素是10个整数的指针
    void print(int (*matrix)[10], int rowSize);
    
    //matrix实际上指向了含有一维整数的数组的开头
    //10被编译器忽略
    void print(int matrix[][10], int rowSize);

    main函数

    //二者等价
    int main(int argc, char *argv[]);
    int main(int argc, char **argv);

    可变形参的函数

    initializer_list形参:参数数量未知,类型相同。

    //定义时
    void error_msg(ErrCode e, initializer_list<string> msgs);
    //调用时,可以看出,实际上还是两个参数,第二参数使用了列表
    error_msg(ErrCode(0), {"function error", "Number error"});

    省略符形参

    仅仅为了访问特殊的C代码,这些代码使用了varargs的C标准库功能。大多说类型对象在传递给省略符形参时,无法正确拷贝,所以一般不用。

    定义方式:void foo(param_list, ...);例如C中的printf函数。

    6.3 函数的返回值

    函数返回的是return之后的副本。

    warming

    由于在函数体内部定义的所有对象在函数结束后都会销毁,所以返回局部变量的指针或引用,将会出现未定义的情况。

    函数返回左值

    只有函数的返回值是引用的时候,返回的值才是左值,其他都是右值。

    可以将返回类型为非常量左值的函数结果赋值。

    //函数定义
    char &get_val(string &str);
    //函数使用
    get_val(str) = 'A';

    返回一个列表

    vector<string> process()
    {
        //...
        return {str1, str2, str3};
    }

    返回数组指针或引用

    因为数组不能被拷贝,所以只能返回数组的指针或者引用。

    //
    using arrT = int[10];
    arrT *func(int i);
    
    //
    int ( *func(int i) )[10];
    
    //③尾置返回类型
    auto func(int i) -> int(*)[10];
    
    //
    int odd[10]={};
    decltype(odd) *func(int i);

    6.4 函数重载

    const形参

    //顶层const无法区分
    Record lookup(Phone);
    Record lookup(const Phone);
    
    //底层const可以区分
    Record lookup(Phone*);
    Record lookup(const Phone*);

    重载中使用const_cast

    //希望如果传递的参数是const的,返回也是const
    //传递的参数不是const的,返回也不是const
    const string &shorterString(const string &s1, const string &s2)
    {
        return s1.size() <= s2.size() ? s1 : s2;
    }
    string &shorterString(string &s1, string &2)
    {
        auto &r = shorterString(const_cast<const string&>(s1),
                                         const_cast<const string&>(s2));
        return const_cast<string &>(r);
    }

    6.5 特殊特性

    默认实参

    函数调用时,用默认实参初始换形参,因此,默认实参可以被一个明确的函数赋值。

    内联函数

    inline

    constexpr函数

    隐式内联的。

    是可以用在常量表达式中的函数。

    函数返回的不一定是常量,此时如用在常量表达式中,编译器会报错。

    6.7 函数指针

    bool lengthCompare(const string &, const strng&);
    
    //声明指向该函数的指针,未初始化
    bool (*pf)(const string &, const strng&);
    
    //初始化该指针,&可选,二者等价
    pf = lengthCompare;    //自动转换成指针
    pf = &lengthCompare;
    
    //使用指针调用,*可选
    bool b1 = pf("hello", "world!");
    bool b1 = (*pf)("hello", "world!");
    
    //使用类型别名
        //函数类型,使用时自动转换为指针
    typedef bool Func(const string &, const strng&);
    typedef decltype(lengthCompare) Func;
        //指向函数的指针类型
    typedef bool (*Func)(const string &, const strng&);
    typedef decltype(lengthCompare) *Func;
    
    
    //函数指针做形参,三者等价
    void useBigger(const string &, const strng&,
                          bool (*pf)(const string &, const strng&));//显式声明了指针参数
    void useBigger(const string &, const strng&,
                          bool pf(const string &, const strng&));
    void useBigger(const string &, const strng&, Func);
    
    //声明返回函数的指针的函数
    bool (*function(...)) (const string &, const strng&);
    Func function(...);    //使用类型别名
    auto function(...) -> bool (*)(const string &, const strng&);    //尾置类型
    decltype(lengthCompare) function(...);
  • 相关阅读:
    (剑指Offer)面试题18:树的子结构
    (剑指Offer)面试题17:合并两个排序的链表
    (剑指Offer)面试题16:反转链表
    程序员水平分级 你属于哪一类?
    Hacker
    十分钟让你看懂中国经济形势,10分钟,坚持看完,必有所获~(转载)
    人口问题,怎样的生育率才能保持正常的世代更替?
    理科和文科的区别?
    柴晓霞:做销售要学会画蓝图 (转载)
    工作,为钱还是为理想
  • 原文地址:https://www.cnblogs.com/qiusuo/p/4478848.html
Copyright © 2011-2022 走看看