• C++Primer笔记-----day03


    ==============================================================
    day03
    ==============================================================
    1.在表达式求值之前,小整数类型的运算对象会被提升成较大的整数类型。
    eg: bool b = true;
    bool b2 = -b; // b2是true! 原因是当b参与运算时,被提升为int类型,即被提升为整数1,求负后为-1,所以b2为真。由此可见,bool类型不应该参与运算。
    2.新标准下,m%(-n)=m%n (-m)%n = -(m%n)
    3.关于位运算。如果运算对象是小整型,则它的值会被自动提升成较大的整数类型。
    位运算的运算对象可以是带符号的,也可以是无符号的。左移操作会改变符号位,关于符号位如何处理依赖于机器,没有明确规定,所以强烈建议仅将位运算用于处理无符号类型。
    4.sizeof运算符计算的是【类型的大小】!与元素个数或者其他什么无关!其所得值是一个size_t类型的常量表达式。用法有两种形式:
    sizeof(type); // 返回此类型所占的字节数
    sizeof(expr); // 返回表达式结果类型的大小。注意:sizeof并不实际计算表达式的值,所以即使此表达式是一个无效的指针也没有什么影响。
    在32位机器上sizeof一个指针,得到4,64位机器得到8.
    注意,sizeof一个数组得到整个数组所占空间的大小。要计算数组中元素的个数,用:sizeof(a)/sizeof(*a)
    还应注意sizeof一个vector或者string,得到的是该类型固定部分的大小,与它里面有多少个元素无关。
    在我的机器上。sizeof(vector<int>) = 16; // 32位机器
    sizeof(vector<char>) = 16; // 还是16 . 由此得出,vector类型的大小,与vector类的具体实现有关。
    ///////////////////////////////////////////////////////////////////////////////////////////////
    5.类型转换。
    (1)大多数用到数组的表达式,数组自动转换成指向数组首元素的指针。
    需要注意的是,当数组被用作decltype关键字的参数,或者取地址符(&)、sizeof、typeid等运算符的运算对象时,上述转换不会发生。
    (2)const_cast类型转换,只能用来改变运算对象的底层const,我们一般称其为“去常量性”。
    eg: const char *pc;
    char *p = const_cast<char*>(pc); // 正确:但通过p写值是未定义的行为。
    注意:const_cast只能改变常量属性,不能用来改变表达式的类型。
    eg: const char *cp;
    const_cast<string>(cp); // 错误
    static_cast<string>(cp); // 正确
    const_cast在重载函数的情景中最有用。
    eg: const string &foo(const string &s1,const string &s2){...}
    这个函数的参数和返回类型都是const string的引用。我们可以对两个非常量的string实参调用这个函数,但结果
    仍然是const string的引用。因此我们需要重载一个foo()函数,当它的实参不是常量时,返回一个普通引用,可以
    使用const_cast做到这一点。
    string &foo(string &s1,string &s2)
    {
    auto &r = foo(const_cast<const string&>(s1),const_cast<const string&>(s2));
    return const_cast<string&>(r);
    }
    这个版本,先将它的实参强制转化为const引用,然后调用了foo()的const版本,这个const版本的foo()返回
    对const string的引用,我们再用const_cast将其转换回一个普通的string&。
    (3)reintepret_cast类型转换非常危险。它可以将一个指针转换成一个int。
    eg:
    int *ip;
    char *pc = reintepret_cast<char*>(ip); // pc所指的真实对象是一个int,如果把pc当成普通字符指针使用,会导致异常的运行时行为。
    string str(pc); // 会导致异常行为
    ////////////////////////////////////////////////////////////////////////////////////////////////
    6.一个函数只能返回一个值,有时函数需要返回多个值,这时,可以多传入一个引用参数,这样就可以通过引用隐式地返回一个值。
    比如,我们想定义一个函数,返回string对象中某个指定字符第一次出现的位置,同时我们也希望得到该字符出现的总次数。
    这时,我们可以给函数传入一个额外的引用参数,让其保存字符出现的次数:
    eg: string::size_type find_char(const string &s, char c, string::size_type &occurs)
    {
    occurs = 0;
    auto ret = s.size();
    for (decltype(ret) i = 0; i != s.size(); ++i) {
    if (s[i] == c) {
    if (ret == s.size())
    ret = i;
    ++occurs;
    }
    }
    return ret; // 出现次数通过occurs隐式地返回
    }

    非常注意的一点是!参数列表的const string &s中的const不可以丢掉。如果丢掉,就不可以用find_char("abcd",'b',ctr)来调用,因为"abcd"本质上是const char*,无法转换为string&,将导致编译出错。
    7.当用实参初始化形参的时候,形参会忽略掉顶层const
    eg: void fcn(const int i){} // 顶层const被忽略
    void fcn(int i){} // 错误,重复定义了fcn(int)
    8.关于数组作为参数传递的问题:
    eg: void print(const int a[10]) // 这里的维度表示我们期望数组含有多少元素,实际不一定。
    这是因为,使用数组时会自动转换为首元素地址。
    再看这个题:
    void print(const int ia[10]) // 语法正确, 但与我们的初衷相违背
    {
    for(size_t i = 0;i != 10;+=i)
    cout<<ia[i]<<endl;
    }

    这里的[10]并不能表示我们要传递一个大小为10的数组,传入const int ia[10],const int ia[100]都是可以的。
    如果我们想传入一个大小为10的数组,应该使用数组的引用 void print(const int (&ia)[10]).
    9.关于默认实参。string screen(int ht = 24, int wid = 80, char bg = ' ');
    需要注意的是,一旦某个形参被赋予了默认值,那么它后面的所有形参都必须有默认值。
    string window;
    window = screen(); // 等价于 screen(24,80,' ')
    window = screen(66,256); // 等价于 screen(66,256,' ')
    10.数组不能被拷贝,所以函数不能返回一个数组,但可以返回数组指针或引用。
    函数形式为: Type (*funcName(parameterList))[dimension]
    eg: int (*func(int i))[10]; //声明了一个函数,返回值为一个指向大小为10的int型数组的指针。
    可以这样理解:
    func(int i)表示调用func函数时需要一个int类型的实参
    (*func(int i))表示我们可以对函数调用的结果执行解引用操作
    (*func(int i))[10] 表示解引用后得到的是一个大小是10的数组
    int (*func(int i))[10] 表示数组中的元素是int型。
    还有其他写法:
    auto func(int i) -> int(*)[10];

    decltype(一个数组) *arrPtr(int i);

    Typedef int arrT[10];
    或者 using arrT = int[10];
    arrT *func(int i);
    11.函数重载调用的匹配规则,考虑如下:
    有两个函数:
    f(int,int);
    f(double,double)
    调用它们f(42,2.56) ,最终编译器会因为这个调用具有二义性而拒绝调用请求。

  • 相关阅读:
    QComboBox设置item height(行高)
    QTabWidget隐藏边框,QWebView/QWebFrame隐藏滚动条
    qt 提示 undefined reference to `vtable for XXX ' 的另一种可能性
    linux double buffering
    http 头信息详解(转载,出处已忘)
    php 魔术方法
    新手使用linux (1)
    关于chm提示 已取消到该网页的导航的解决方法(转载,忘记出处)
    redis 中文文档
    php PDO (转载)
  • 原文地址:https://www.cnblogs.com/ll-10/p/9588168.html
Copyright © 2020-2023  润新知