局部静态变量,关键字static修饰,即使函数结束执行也不受影响,生存期直到程序终止。

  java中static的单一存储空间的概念与其或有异曲同工之妙。

函数的形参可以无名,但有名可以使其意义更加清晰。

分离式编译的一种模式:头文件中声明函数,在name.cpp文件中定义,最后在name_main.cpp中实现

若函数传值调用,则实参和形参为两个独立的个体;若函数传引用调用,形参为实参的别名,即同一个体

形参为指针

  例如:void reset(int *p){

      *p=0;//解引用改变所指对象的值

      }

     int i=24;

     reset(&i);//此时i==0

形参为引用

  例如:void reset(int &p){

      p=0;}//p所引用的对象的值被改变

    int j=24;

    reset(j);//此时j==0,reset内部对 p 的操作即为对 j 的操作

  如果类类型过大或者就不支持拷贝,则需要以引用为函数形参(如果不希望改变对象的值,参数类型应为const)

  另外传引用可以获得额外信息,在函数使用完毕后,传入的参数其值保留

若函数的形参为顶层const,传入非const参数作为实参是允许的(此时顶层const被忽略,故仅仅有无const不能重载函数)

  与上一条相对地,若形参为非常量,则禁止传入常量实参

若非必要,引用型形参尽量是常量引用,若函数嵌套调用时内外层引用形参不同为常量/非常量,易引发错误

  例如:void func1(const string &s){

      /*.........................*/

      func2(/*string*/ s);}//此例即不通

数组形参

  例如:void func(const int*);

     void func(const int [ ]);

     void func(const int [10]);//仅表示希望的元素个数,实际调用不一定,与前两条等价

  防止越界的操作:

  例如:void print(const char *cp){

      if(cp)//非空指针

        while(*cp)//非空字符

          cout<<*cp++;}//向后位移

  也可:void print  (const char *beg,const char *end){//end是尾后元素

      while(beg!=end)//输出不含end的所有元素,end可由end(arr)获取,begin可由begin(arr)获取

        cout<<*beg++;}

  也可:void print  (const int ia[ ],size_t size){

      for(size_t i=0 ; i != size; i++){

        cout<<ia[ i ];}//显式固定大小

数组引用形参

  例如:void print( int (&arr)[10]){//注意括号位置

      for(auto elem:arr)

        cout<<elem;}//不足是大小固定  

多维数组形参

  例如:void print( int (*matrix)[10], int rowsize){/*.............*/}

处理命令行选项时,main函数需要参数:int main(int argc,char* argv[ ])

可变形参

  initializer_list形参:(形参数目未知,类型相同)

  

initializer_list<T> lst 默认初始化,T类型空列表
initializer_list<T>lst{a,b,c...} const T 类型元素与lst列表中数量相同,是对应初始值的副本
lst2(lst)或lst2=lst 拷贝或赋值initializer_list对象,但不赋值列表中的元素,原列表和副本共享元素
lst.size() 列表元素数量
lst.begin() 指向lst首元素的指针
lst.end() 指向lst尾后元素的指针

 

  例如:void print(initializer_list<string> lst){

      for(auto beg=lst.begin();beg!=lst.end();beg++)

        cout<<*beg;   }

     print({"FunctionX","Okey"});//调用时必须带花括号

  省略符形参:(并不好用,传递参数容易出错)

  例如:void foo(int,...);

     void foo(...);//省略符必须在参数列表末尾

返回值和return

  不要返回局部对象的指针或引用(函数完成后,局部对象就已经不存在了)   

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

  c++11允许返回一组花括号括起来的列表(列表初始化返回值),若为内置类型列表内仅能包含最多一个值:

   例如:vector<string>process(){

      /*..........*/return{};

      /*..........*/return{"Hello","World"}; }

  返回数组指针(指向数组的指针):(如果不想使用类型别名,定义的名字后面数组的元素个数要记住)

  例如: int(*func(int i))[10];

  尾置返回类型(c++11):像是返回数组指针或者数组引用之类的复杂类型较为合适,当然所有类型返回值都可用

  例如:auto func(int i)->int(*)[10];(得到了与上一条相同的效果,而且更加清晰)

  使用decltype(c++11):(已知返回的指针指向哪个数组)

  例如:int odd[ ]={1,3,5,7,9};

     int even[ ]={2,4,6,8,10};

     decltype(odd) *func(int i){//注意此处*不能省

      return (i%2)?&odd:&even;}

仅仅返回类型不同不能构成重载函数,函数的形参列表是否为顶层const并无区别,然而形参是否为底层const对函数确有影响

如chap4所示,const_cast<type>objname在重载函数中很有用,如果希望消除某一变量的const性质,此举是唯一方法

注意:名字查找在类型查找之前(局部作用域内的新声明会覆盖外层同名对象,导致内部调用时引发错误)

在函数声明的形参列表中可以提供默认值(要么所有形参都有默认值,要么就都没有):

  例如:string screen(size_type ht=24,size_type wid=80,char background=' ');

     screen();//等价于screen(24,80,' ');

     screen(44);//等价于screen(44,80,' ');

     screen(22,88);//等价于screen(22,88,' ');

     也就是说,提供的值必须是按照声明顺序的,调用screen('?');等价于screen('?',80,' '); 显然不合法

内联函数inline:声明函数之前加上inline关键字,可以使其调用更快(至于内联是否生效看编译器是否批准内联请求,通常用于结构较为简单的函数)

constexpt函数:函数的返回值类型及所有形参的类型都是字面值类型,而且函数体中必须有且只有一条return语句;

          如果调用实参为常量,返回常量表达式,调用非常量,返回的也非常量(使用此函数在定义函数前加上constexpr关键字)

通常内联函数和constexpr函数被定义在头文件中(因为允许此两种函数在程序中多次定义)

assert预处理宏(断言):(#include<cassert>)

  例如:assert(expression);//expression==true,assert什么也不做;expression==false,程序终止并返回信息

处理调试状态

  定义预处理变量NDEBUG:#define NDEBUG:关闭调试状态(此举可使assert无效)

  除了使用assert,也可以自定义条件调试代码:

    void print(const int ia[ ],size_t size){

      #ifndef NDEBUG

        cerr<<__func__<<":array size is "<<size;

      #endif}

    __func__存放函数名字的字符串字面值(这里输出当前调试的函数名)

    __FILE__存放文件名的字符串字面值

    __LINE__存放当前行号的整型字面值

    __TIME__存放文件编译时间的字符串字面值

    __DATE__存放文件编译日期的字符串字面值

函数指针:指向的是函数而非对象

  例如:bool lengthCompare(const string&,const string&);

     bool (*bf)(const string&,const string&);//要求返回类型和形参类型及数量完全一致

     bf =0;//表示不指向任何函数

     bf=&lengthCompare;(或bf=lengthCompare;)//bf指向函数lengthCompare

     bf("Hello","World");(或(*bf)("Hello","World");)//利用bf调用函数lengthCompare,无须提前解引用指针

      void usePointer(const string&,const string&,bf(const string&,const string&));//这里usePointer函数的第三个参数是函数指针,与上面的bf相同性质

  使用类型别名表示返回类型式函数指针:尾置返回类型也可(auto f1(int)->int(*)(int* ,int))

     using PF=int(*)(int*,int);//PF是指针类型  PF f1(int);

     using F=int (int* ,int);//F是函数类型  F *f2(int);//显式地表示返回函数指针,*不能省

  r若已知返回的函数是哪个:

     int func1(const int&,const int&);

     int func2(const int&,const int&);

     decltype(func1) *usefcn(const int&);//注意此处*不能省,decltype得到的是函数类型

//本章概念较为混乱,需多看多记

            

                  

C++Primer 5th Chap6 Functions的更多相关文章

  1. C++Primer 5th 练习 12.19

    这阵子真是太忙了, 连续做了四个课设. 当然这并不能作为好久没写博客的借口, 没写博客的主要原因只有一个: 懒. 最近又开始回顾C++的语法与特性(据说C++就是一门需要反复回顾的语言),以及学习C+ ...

  2. 【读书笔记】C++ primer 5th 从入门到自闭(一)

    这几天看了C++ primer 5th的一二章,有很多收获,但是有的地方因为翻译的问题也搞得理解起来颇为难受啊啊啊啊.尤其是const限定符,在C语言并没有这么多复杂的语法,在C++里面语法细节就多的 ...

  3. C++ Primer 5th 第1章 开始

    *****代码在Ubuntu g++ 5.31 / clang++ 3.8(C++11)下编写调试***** 每个C++程序必须有一个main( )函数,main( )函数的返回值也必须是int类型, ...

  4. c++ primer 5th 练习3.43

    #include <iostream> using namespace std; int main() { ][]={,,,,,,,,,,,}; /* for(int (&i)[4 ...

  5. C++ Primer 5th 第16章 模板与泛型编程

    模板是C++中泛型编程的基础,一个模板就是创建一个类或者函数的蓝图或者说公式. C++模板分为函数模板和类模板. 类模板则可以是整个类是个模板,类的某个成员函数是个模板,以及类本身和成员函数分别是不同 ...

  6. C++ Primer 5th 第15章 面向对象程序设计

    面向对象程序设计的核心思想是:数据抽象.继承和动态绑定. 数据抽象:将类的接口与实现分离: 继承:定义相似类型并对相似关系建模: 动态绑定:一定程度上上忽略相似类型间的区别,用同一方式使用它们. 1. ...

  7. C++ Primer 5th 第13章 拷贝控制

    当一个对象的引用或者指针离开作用域时,析构函数不会执行. 构造函数有初始化部分(初始化列表)和函数体. 析构函数有析构部分和函数,但析构函数的析构部分是隐式的.

  8. C++ Primer 5th 第12章 动态内存

    练习12.1:在此代码的结尾,b1 和 b2 各包含多少个元素? StrBlob b1; { StrBlob b2 = {"a", "an", "th ...

  9. C++ Primer 5th 第11章 关联容器

    练习11.1:描述map 和 vector 的不同. map是关联容器,vector是顺序容器,关联容器与值无关,vector则与值密切相关 练习11.2:分别给出最适合使用 list.vector. ...

随机推荐

  1. Java学习日记基础篇(九) —— 集合框架,泛型,异常

    集合框架 有事我们会需要一个能够动态的调整大小的数组,比如说要添加新员工但是数组已经满了,并且数组的大小是在定义的时候定死的,所以我们就需要一个能够动态调整大小的数组或者用链表解决,而java中提供了 ...

  2. 享学课堂java架构vip课程

    1.wps文档地址 https://docs.qq.com/doc/DRVNLUndvTmFSdEhO 2.百度网盘地址 https://pan.baidu.com/s/1uxaTzJZHKrsw_H ...

  3. ibm 汇编

    https://www.ibm.com/developerworks/cn/linux/l-assembly/index.html https://72k.us/file/4031001-328073 ...

  4. Java核心复习 —— J.U.C 并发工具类

    一.CountDownLatch 文档描述 A synchronization aid that allows one or more threads to wait until* a set of ...

  5. LightGBM与评分卡

    调参策略 最大化 off_ks + 0.8(off_ks-train_ks) import pandas as pd from sklearn.metrics import roc_auc_score ...

  6. 微信小程序测试检查点

    1.权限测试 需要检查以下几种情况下微信用户访问的权限1)未授权微信登录小程序未授权时,一般使用一些业务功能的时候,都会弹出提醒:先授权再操作对应功能.或在提交数据到后台的时候,会提示补充相关身份信息 ...

  7. @Deprecated注解

    它的作用是对不应该再使用的方法添加注解,当编程人员使用这些方法时,将会在编译时显示提示信息,它与javadoc里的@deprecated标记有相同的功能,准确的说,它还不如javadoc @depre ...

  8. SSH工具登录远程指定节点时输入用户名密码方式【我】

    通过堡垒机部署项目, 一种方式:先把补丁传到接入机,然后用CRT等命令行工具登录指定接入机,然后用SCP命令把 补丁传到 生产服务器,比如 scp -P90010 /app/backup/packet ...

  9. osg模型部分节点旋转

    osg::ref_ptr<osg::Geode> CreateBox() { osg::ref_ptr<osg::Geode> geode = new osg::Geode; ...

  10. 【425】堆排序方法(二叉堆)优先队列(PQ)

    参考:漫画:什么是二叉堆? 大根堆 小根堆 参考:漫画:什么是堆排序? 参考:漫画:什么是优先队列? 参考:[video]视频--第14周10--第8章排序10--8.4选择排序3--堆排序2--堆调 ...