C++ Primer点滴(待续)

    技术2022-05-20  29

    1. const形参

        如果使用形参的唯一目的是避免复制实参,则应该将形参定义为const,即应该将不需要修改的引用参数定义为const引用。普通的非const引用形参在使用时不太灵活。这样的形参既不能用const对象初始化,也不能用字面值或产生右值的表达式实参初始化。

    int incr(int &val) { return ++val; } void main() { short v1 = 0; const int v2 = 42; int v3 = incr(v1); //error: v1 is not an int v3 = incr(v2); //error: v2 is const v3 = incr(0); //error: literals are not lvalues v3 = incr(v1+v2); //error: addition doesn't yield an lvalue int v4 = incr(v3); //ok, v3 is a non const object type int }

    2. 关于形参

        函数的参数传递包含以下几种:

        2.1 非引用形参 int func(int v1); int func(int *p)

        2.2 引用形参 void swap(int &v1, int &v2)

        2.3 传递指向指针的引用 void ptrswap(int *&v1, int *&v2),其中int *&v1应该从右向左理解:v1是一个引用,与指向int型对象的指针相关联。

        2.4 假如是数组形参,通常将数组形参直接定义为指针要比使用数组语法定义更好。这样就明确表示,函数操纵的是指向数组元素的指针,而不是数组本身。由于忽略了数组长度,形参定义中如果包含数组长度则特别容易引起误解。另外当编译器检查数组形参时,它只会检查实参是不是指针、指针的类型是不是和数组元素匹配,而不会检查数组的长度。

     

    3. 关于return

        返回值谨记两点:千万不要返回局部对象的引用,千万不要返回指向局部对象的指针。

     

    4. 关于内联函数

        调用函数比求解表达式要慢得多,因为涉及到保存寄存器等工作。内联函数优点是可以避免函数调用的开销。即在编译时就将展开为内联函数的语句,从而消除了调用函数的额外开销。

        内联函数应该在头文件中定义,这一点不同于其他函数。

        类的成员函数可以在类内定义,也可以在类外定义,编译器隐式地将类内定义的成员函数当作内联函数。

     

    5. 关于const成员函数

        5.1 成员函数声明为const, 表明它们不修改类对象。

        5.2 只有被声明为const 的成员函数才能被一个const 类对象调用。关键字const 被放在成员函数的参数表和函数体之间。对于在类体之外定义的const 成员函数,我们必须在它的定义和声明中同时指定关键字const。    5.3 把一个成员函数声明为const 并不能阻止程序员可能做到的所有修改动作。把一个修改类数据成员的函数声明为const 是非法的。但是,如果该类含有指针,那么在const 成员函数中就能修改指针所指的对象。    5.4 const 成员函数可以被相同参数表的非const 成员函数重载。

     

    6. 使用下标访问map对象

        map<string, int> word_count;

        word_count["Anna"] = 1;

        将发生以下事情:

        (1)查找word_count中键为Anna的元素,没有找到;

        (2)将一个新的键-值插入到word_count中,它的键是const string类型的对象,保存Anna。而它的值则采用值初始化,这意味着在本例中值为0;

        (3)将这个新的键-值插入到word_count中;

        (4)读取新插图的元素,并将它的值赋为1。

        注:使用下标访问map与使用下标访问数组或者vector的行为截然不同,用下标访问不存在的元素将导致在map容器中添加一个新元素,它的键值即为下标值。但是如果该键值已经在容器中,则map的下标运算与vector的下标运算行为相同。可以比较如下例子:

        map<int, int> m; m[0] = 1;

        vector<int> v; v[0] = 1;

     

    7. 关于静态数据成员

        7.1 不要试图在头文件中定义(初始化)静态数据成员。在大多数的情况下,这样做会引起重复定义这样的错误。即使加上#ifndef #define #endif或者#pragma once也不行。 

    static成员变量不属于对象的一部分,而是类的一部分,所以程序可以在还没有诞生任何对象的时候就处理此种成员变量。但是首先你必须初始化它。 初始化static成员变量不能安排在类的构造函数中,因为构造函数可能一再被调用,而变量的初值却只应该设定一次。也不要把初始化安排在头文件中,因为它可能会被包含在许多地方。而应该放在main函数之中,或全域函数中,或者任何函数之外。

        7.2 静态数据成员可以成为成员函数的可选参数,而普通数据成员则不可以。举例如下: 

    class base{  public :  static int _staticVar;  int _var;  void foo1(int i=_staticVar);//正确,_staticVar为静态数据成员  void foo2(int i=_var);//错误,_var为普通数据成员  }; 

        7.3 静态数据成员的类型可以是所属类的类型,而普通数据成员则不可以。普通数据成员的只能声明为 所属类类型的 指针或引用。举例如下:

    class base{  public :  static base _object1;//正确,静态数据成员  base _object2;//错误  base *pObject;//正确,指针  base &mObject;//正确,引用  };      7.4  静态成员函数不可以调用类的非静态成员。因为静态成员函数不含this指针。

        7.5 静态成员函数不可以同时声明为 virtualconstvolatile函数。


    最新回复(0)