c++ primer 笔记,第六章

  1. 局部静态对象使用static声明,声明一次后下次再调用该函数,则该声明语句则被忽略

    // 练习6.7,第一次被调用时返回0,以后每次调用返回值加一 
    size_t count()
    {
        static size_t ctr = 0;
        if (ctr) return ctr++;
        else 
        {
            ++ctr;
            return 0;
        }
    }
  2. 当函数无需修改引用形参的值时最好使用常量引用

  3. 使用实参初始化形参时会忽略顶层const
  4. 使用普通引用会极大地限制函数所能接受的实参类型,我们不能把const 对象、字面值或者需要类型转换的对象传递给普通的引用形参

    // 由于该形参为非常量引用,若定义一个const string或者字面值常量,则无法调用该函数 
    bool is_empty(string &s)  { return s.empty(); } 
  5. 如果所有实参类型相同,可以传递一个名为initializer_list的标准库类型用来实现可以处理不同数量实参的函数,类型定义在同名头文件中
    (1)与vector一样,该类型也是一种模板类型,但其对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值;
    (2)拷贝或赋值一个initializer_list对象不会拷贝列表中的元素;拷贝后,原始列表与副本共享元素(因为该对象中的元素不可能被改变,所以在赋值或拷贝的行为中完全可以与原始列表共享而不用担心其他任何问题,并且还避免了拷贝的开销);
    (3)lst.size(), lst.begin(), lst.end();
    (4)如果想向initializer_list形参中传递一个值的序列,则必须把序列放在一对花括号中;

    // 练习6.27 
    template<typename T>
    int sum(initializer_list<T> lst)
    {
        int sum = 0;
        for(const auto &beg : lst)   // const auto& 型,避免多余的拷贝行为发生 
            sum += beg;
        return sum;
    } 
    
    int main()
    {
    /*  
        for (int i = 0; i < 10; ++i)
            cout << count() << endl;
    */
        cout << sum({2,3,4,5}) << endl;  //实参必须放在一对花括号中 
        cout << sum({1,2,3}) << endl;
        return 0;
    }
  6. return语句有两种形式,一种是空return,即 return,另一种是返回一个表达式,即return expression ;一个返回类型是void的函数也能使用return 语句的第二种形式,不过此时 return 语句的 expression 必须是另一个返回void的函数
  7. 调用运算符的优先级与点运算符和箭头运算符相同,并且也符合左结合率,如果函数返回指针、引用或类的对象,我们就可以使用函数调用的结果访问结果对象的成员
  8. C++11新标准规定,函数可以返回花括号包围的值的列表,如果函数返回的是内置类型,则花括号包围的列表最多包含一个值,如果函数返回的是类类型,由类本身定义初始值如何使用

    
    #include <iostream>
    
    
    #include <vector>
    
    using namespace std; 
    //例:该函数返回值为vector<string>类型 
    vector<string> process()
    {
        return {"abc", "cd"};
    } 
    
    int main()
    {
        vector<string> a;
        a = process();
        cout << a[0] << endl;
        return 0;
    }
  9. 关于返回数组指针:

    typedef int arrT[10];   //arrT是一个类型别名,它表示的类型是含有10个整数的数组
    
    using arrT = int[10];   // 等价于上面的声明
    
    arrT* func(int i);      // func返回一个指向含有10个整数的数组的指针

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

  10. 尾置类型返回,在本该出现返回类型的地方放置一个auto, 例如:auto func(int i) -> int(*0[10];

  11. 关于函数重载:
    (1)重载函数中不允许两个函数除了返回类型不同其他类型都相同,即意味着返回类型不能用来区别函数

    int  func(int i);
    bool func(int i);    // 错误:遇上一个函数相比只有返回类型不同 

    (2)拥有顶层const的形参无法和无顶层const的形参区别开来;

    int  func(int );
    int  func(int* const);    // 错误:重复声明了func 

    (3)如果形参是某种类型的指针或引用,则可以通过区分其指向的是常量对象还是非常量对象可以实现函数重载,此时的cons是底层的

    int  func(int& );
    int  func(const int&);    // 作用于常量引用 
  12. const_cast再函数重载中的作用,如果一个函数的形参为const版本,返回值为const&的类型,此时若想用非常量实参使用该函数,并得到一个普通的引用,可以使用const_cast先将非常量实参转换为常量引用,调用const版本函数,然后对返回结果再用const_cast转换为普通引用,保障整个过程的安全

  13. 一旦一个形参被赋予了默认值,则它后面的所有实参都必须有默认值,在给定的作用于中一个形参只能被赋予一次默认值,后续的函数声明只能为没有默认值的形参添加默认实参

    string func(a,b,char = ' ');
    
    string func(a,b,char = '*');   //错误,重复声明
    
    string func(a = 5, b = 8, char);  // 正确,在此之前char已经有默认值 
  14. constexpr函数的返回值及所有形参类型都得是字面值类型(在编译时就得到计算,算数类型、引用和指针都属于字面值类型,自定义类,IO库、string类型都不属于字面值类型),而且函数体中有且只有一条return语句 ;为了嗯那个在编译期间随时展开,constexpr函数被隐式地指定为内联函数,我们允许constexpr函数返回值并非一个常量(返回结果可以是一个常量表达式);
  15. assert的行为依赖于一个名为NDEBUG的预处理变量的状态,如果定义了NDEBUG,则assert什么也不做,默认状态下没有定义NDEBUG ;
  16. 预处理器定义的5个名字 (头文件为cstdio)
    (1)_ _fun_ _:当前调试的函数的名字;
    (2)_ _FILE_ _ :存放文件名的字符串字面值;
    (3)_ _LINE_ _:当前行号;
    (4)_ _TIME_ _:文件编译时间;
    (5)_ _DATE_ _:文件编译日期;
  17. 可以直接使用和i资讯那个函数的指针调用该函数,无需提前解引用指针

    // func函数返回一个函数指针,该函数指针所指的函数的形参为一个int* 和一个 int,返回值为int 
    int (*func(int)) (int*, int);
    // 等价于 
    using PF = int(*)(int*, int);
    PF func(int);
    // 等价于
    auto func(int) -> int (*)(int*, int);
发布了48 篇原创文章 · 获赞 17 · 访问量 2万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览