zoukankan      html  css  js  c++  java
  • Chapter6:函数

    执行函数的第一步是(隐式地)定义并初始化它的形参。所以,函数最外层作用域中的局部变量也不能使用与函数形参一样的名字

    局部静态变量:在程序的执行路径第一次经过对象定义语句时初始化,并且直到程序终止才被销毁。在此期间即使对象所在的函数结束执行也不会对它产生影响。

    Best Practice:熟悉C的程序员常常使用指针类型的形参访问函数外部的对象。在C++中,建议使用引用类型的形参代替指针

    使用引用避免拷贝:因为:拷贝大的类类型对象或者容器对象比较低效;有些类类型根本不支持拷贝操作;

    当用实参初始化形参时会忽略掉顶层const。

    我们可以使用非常量初始化一个底层const对象;但是,反过来不行。

    尽量使用常量引用

    1 string::size_type find_char(string &s, char c, string::size_type &occurs);
    2 find_char("hello world", 'o', ctr);//用字面值常量绑定到string引用,编译错误
    3 
    4 bool is_sentence(const string &s)
    5 {
    6     string::size_type ctr = 0;
    7     return find_char(s, '.', ctr) == s.size() - 1 && ctr == 1;//错误
    8 }
    (上述两种错误)

    数组的两个特殊性质对我们定义和使用作用在数组上的函数有影响,这两种性质分别是:1)不允许拷贝数组;2)使用数组时会将其转换成指针。

    • 管理指针的三种常用技术

    1. 使用标记指定数组长度,典型示例是C风格字符串

    1 void print(const char *cp)
    2 {
    3     if (cp)
    4         while (*cp)
    5             std::cout << *cp++;
    6 }

    2.使用标准库规范:传递指向数组首元素和尾后元素的指针

    1 void print(const int *beg, const int* end)
    2 {
    3     while (beg != end)
    4         std::cout << *beg++ << std::endl;
    5 }

    3. 显示传递一个表示数组大小的形参:在C程序和过去C++程序中常用这种办法

    1 void print(const int a[], size_t size)
    2 {
    3     for (size_t i = 0; i != size; ++i)
    4         std::cout << a[i] << std::endl;
    5 }

    含有可变形参的函数:C++11风格:1)如果所有实参类型相同,可以传递一个名为initializer_list的标准库类型;2)如果实参类型不同,可以使用可变参数模板;C风格:3)varargs

    与vetor不同的是,initializer_list对象中的元素永远是常数值,无法更改。

    • return

    返回一个值的方式和初始化一个变量或形参的方法完全一样:返回的值用于初始化调用点的一个临时量,该临时量就是函数调用的结果。

    调用一个返回引用的函数得到左值;其他返回类型得到右值。

    C++11可以列表初始化返回值。

    • 返回数组指针

    如果我们想定义一个返回数组指针的函数,则数组的维度必须跟在函数名字和形参列表之后。

    1 int(*func(int i))[10];
    2 //func(int i)表示调用func函数需要int参数
    3 //(*func(int i))意味着我们可以对函数调用的结果执行解引用
    4 //(*func(int i))[10]表示解引用将得到一个大小是10的数组
    5 //int(*func(int i))[10]表示数组中的元素是int类型

    C++11新方法:尾置返回类型

    auto func(int i) -> int (*) [10]

    亦或者使用decltype,但是记住:decltype并不负责将数组类型转换成对应的指针,所以decltype结果是数组

    1 int odd[] = { 1,3,5,7,9 };
    2 int even[] = { 0,2,4,6,8 };
    3 decltype(odd) *arrPtr(int i)
    4 {
    5     return (i % 2) ? &odd : &even;
    6 }
    • 函数重载与函数匹配

    顶层const不影响传入函数的对象。

    函数匹配有三种结果:1)找到最佳匹配;2)无匹配;3)二义性匹配;

    如果我们在内层作用域中声明名字,它将隐藏外层作用域中的同名实体。在不同作用域中无法重载函数名。在C++中名字查找发生在类型检查之前。

    函数匹配的步骤

    (1)寻找候选函数:1)与被调用函数同名;2)声明在调用点可见;

    (2)寻找可行函数:1)形参与实参数量相等;2)对应类型相同或者是能转换成形参类型

    (3)寻找最佳匹配:实参类型与形参类型越接近,匹配得越好

    匹配等级具体排序如下

    1.精确匹配:分情况:1)实参类型与形参类型相同;2)实参从数组类型或函数类型转换成指针类型;3)实参添加/删除顶层const。

    2.通过const转换实现的匹配;

    3.通过类型提升实现的匹配(有int型形参,有short形参,则char直接提升为int)

    4.通过算术类型转换实现的匹配,所有转换等级都一样;

    5.通过类类型转换实现的匹配。

    在给定作用域中一个形参只能被赋予一个默认实参,换句话说,函数的后续声明只能为之前那些没有默认值的形参添加默认实参。

    默认实参的解析求值发生在函数调用时。

    constexpr函数不一定是常量表达式

    把内联函数和constexpr函数放到头文件中,编译时使用。

    调试帮助:

    assert的行为依赖于NDEBUG的状态,如果NDEBUG定义了,那么assert什么也不做。

    函数指针:decltype作用于函数时,返回的是函数类型而非指针类型。

  • 相关阅读:
    aspcms产品详情页调取相关产品
    构造函数中返回一个对象对结果有什么影响
    跨域的几种方法及案例代码
    localStorage兼容方案
    H5 拖放事件详解
    由作用域安全的构造函数想到的
    valueOf和toString的区别
    网页布局--自适应
    【MongoDB系列】简介、安装、基本操作命令
    【JavaWeb】之Servlet
  • 原文地址:https://www.cnblogs.com/wangyanphp/p/5776935.html
Copyright © 2011-2022 走看看