第六章 函数

来源:互联网 发布:仓管软件免费版 编辑:程序博客网 时间:2024/06/07 00:39

一、参数传递

        1、在C++中建议使用引用类型的形参替代指针类型的形参。使用引用同时也能避免参数传递时的拷贝,可以提高效率。如果某些类型不支持拷贝操作(如IO类型),函数只能通过引用形参访问该类型对象。如果函数无须改变引用形参的值,最好将其使命为常量引用

    // 比较两个string对象的长度    bool isShorter(const string &s1, const string &s2)    {        return s1.size() < s2.size();    }

        2、指针或引用形参与const:形参的初始化方式和变量的初始化方式是一样的。

        3、数组形参:

    char str[] = "Fuck you!";    // 以下三个函数形式都可以用str数组传参,在函数中都可以使用形参对str数组进行访问    print(const char str[])    print(const char str[10])    print(const char *str)

        以上函数在使用形参的时候并不知道实参数组的大小,所以可能引发数组越界。所以产生了以下三种管理指针形参的技术

  • 使用标记指定数组长度
    void print(const char *str){    if(str)while(*str)// 只要指针所指的字符不是空字符标记    cout << *str++;    cout << endl;}// 以上对于像int类型的数组就不太适用了
  • 使用标准库规范:传递数组首元素和尾后元素的指针
    int ia[] = {1,2,3,4,5,6};void print(const int *beg, const int *end){    while(beg != end)        cout << *beg++;    cout << endl;}// 使用C++ 11标准提供的begin()和end()函数获取数组的首元素指针和尾后指针并作为实参调用函数print(begin(ia), end(ia));
  • 显式传递一个表示数组大小的形参
    // const int ia[] 等价于 const int *iavoid print(const int ia[], size_t size){    for(size_t i = 0; i != size; ++i)    {cout << ia[i];    }    cout << endl;}// 调用printprint(ia, end(ia) - begin(ia));

        函数参数允许定义为数组的引用:

    void print(int (&ia)[10]);// 定义时的小括号比不可少,纬度是类型的一部分    int i = 0, j[2] = {0,1}, k[10] = {0,1,2,3,4,5,6,7,8,9};    print(&i);// 错误:数组长度不是10    print(j);// 错误:数组长度不是10    print(k);// 正确

        4、传递多维数组参数

    // 由于多维数组就是数组的数组,在传递多维数组时应该用以下的方式定义    void print(int (*matrix)[10], int rowSize);// 传递的数组是由10个整数构成的数组    voed print(int matrix[][10], int rowSize);// 与上是等价定义

        5、含有可变形参的函数

  • 实参类型相同:传递initializer_list的标准库类型(头文件<initializer_list>),提供以下操作:
    initializer_list<T> list;                    // 默认初始化
    initializer_list<T> list{a,b,c,d};       // list的元素是对应初始值的副本;列表中的元素是const类型的
    list2(list);
    list2 = list;
    list.size();                                      // 列表中元素的数量
    list.begin();                                    // 返回list中首元素的指针
    list.end();                                       // 返回指向list中尾元素下一位置的指针
  • 省略符形参
  • 可变参数模版

 

二、因为数组不能拷贝赋值,所以函数不能返回数组。不过,函数可以返回数组的指针或引用。定义一个返回数组的指针或引用的函数的方法如下:

    typedef int iarrT[10];// 含有10个整数的数组类型    using iarrT = int[10];// 与上等价定义    iarrT* function(int i);// 使用类型别名定义    int (*function(int i))[10];// 这种原始定义太繁琐    auto function(int i) -> int(*)[10];// C++11中的尾置返回类型    decltype(iarrT) *function(int i);// 使用C++11中的decltype类型推断定义

 

三、特殊用途语言特性

        1、默认实参:一旦某个形参被赋予了默认值,它后面的所有形参都必须有默认值。
        2、内联函数:内联函数可以避免函数调用的开销。一般来说,内联机制用于优化规模较小、流程直接、频繁调用的函数。很多编译器都不支持内联递归函数,而且一个几十行上百行的代码也不大可能在调用点内联的展开。

              constexpr函数:是指能用于常量表达式的函数。约定:函数的参数和返回值都得是字面值类型,而且函数中必须有且只有一条return语句,函数内可以有其他语句,只要这些语句在运行时不执行任何操作就行。constexpr函数返回的不一定是常量表达式。

              通常把内联函数和constexpr函数定义在头文件内。

        3、assert(expr)。assert宏在头文件cassert中定义。
             NDEBUG预处理变量。#define NDEBUG 后,不在运行assert语句。除了用assert以外,还可以结合使用#ifndef NDEBUG、#endif编写自己的条件调试代码。
             预处理器定义了另外4个对调试程序很有用的名字:__FILE__、__LINE__、__TIME__、__DATE__。

 

四、函数指针

    bool lengthCompare(const string &str1, const string &str2);    bool (*pf)(const string &, const string &);// *pf两端的括号必不可少    pf = lengthCompare;     pf = &lengthCompare;// 取地址符是可选的    bool b1 = pf("hello", "goodbye");    bool b2 = (*pf)("hello", "goodbye");    bool b3 = lengthCompare("hello", "goodbye");


 

0 0
原创粉丝点击