zoukankan      html  css  js  c++  java
  • Thinking in C++ 第8,9,10章(const成员函数、内联函数、静态对象的析构函数调用时机)

    一、const成员函数

    1. 编译器认为非const的成员函数会改变对象中的数据成员,因此编译器不允许它被const对象所调用。

    2. const在函数定义中被认为是函数标识符的一部分,编译器和链接器都会检查const。因此若要定义一个const成员函数,需要在声明和定义中同时出现const声明。

     

    按位(bitwise)const和按成员(memberwise)const

    按位const的意思是,对象中的每个字节都是固定不变的。按成员const意思是,虽然整个对象从概念上讲是不变的,但是可以改变某个成员。当声明一个const对象时,它默认是按位const的,有两种有内部const成员函数改变数据成员的方法:

    1. 强制转换常量性(casting away constness)

    首先,在const成员函数内部,this实际上是一个const指针,想要改变它的某个成员,需先将this转换成普通的指针,例如:

    1 class C{
    2 private:
    3     int i;
    4 public:
    5     void func()const{
    6        ((C*)this)->i++;              // 将this由const C*强制转换为C*
    7        const_cast<C*>(this)->i++;    // C++风格的转换方式
    8     }
    9 };

    2. 使用mutable关键字

    如果一个数据成员被mutable关键字修饰,那么说明这个成员在const成员函数中可以被修改,如下所示:

    1 class C{
    2 private:
    3     mutable int i;  // 使用mutable进行修饰
    4 public:
    5     void func()const{
    6        i++;  // i使用mutable修饰,可以对其进行修改
    7     }
    8 };

    只读存储能力

    如果一个对象被定义为const对象,它就成为了被放进ROM中的候选者,这经常是嵌入式系统所需要考虑的重要事情,

    一个const对象可以被放入ROM中所需具备的条件:

    1. 必须是按位const

    2. classstruct没有用户定义的构造函数或析构函数;

    3. 不能有基类,它的数据成员类型也不能包含用户定义的构造函数或析构函数。

    二、内联函数

    宏的缺陷

    C中,保持效率的一个方法是使用宏(macro),宏看起来像函数,但它不需要函数调用的开销。但是在C++中宏存在三个问题:

    1. 宏外观上像函数,但并不是函数,它的某些行为容易导致错误的发生;

    2. 宏不允许访问类中的成员;

    3. C++中,不能对宏进行访问控制,因为宏从它定义的地方开始有效。

     

    内联函数

    内联函数本质上是一个函数,它具备函数所具备的一切特征,唯一不同的是,当编译器发现内敛函数在某个地方被调用时,它会将内联函数像宏一样展开。因此内联函数的调用不需要开销。

    内联函数的链接方式属于内部链接,内联函数的定义应放在头文件中,在内联函数调用点处,它的定义必须是可见的。内联函数在程序中的定义可能不止一处,但在一个源文件中只能出现一次,而且在所有源文件中其定义必须完全相同。

    内联函数的定义

    1. 对于一般的函数需在声明和定义前加inline关键字

    2. 对于类成员函数,在类体内定义的默认的就是内联函数(对于短小的成员函数,一般都定义在类体内),不必使用inline关键字进行修饰;若在类体外定义,只需在定义前加inline关键字就行了,且这个定义必须与包含它的类放在同一个文件中。建议,所有函数定义都放到类外部以保持接口清晰。

     

    内联函数的限制

    通常情况下,编译器不会为内联函数建立存储空间,但是,如果违反内联函数的规则,编译器就会简单地将内联函数视为普通函数,为其分配存储空间。下面是内联函数的一些规则:

    1. 如果函数太复杂,编译器将不执行内联。

    2. 如果要显示或隐式地取内联函数的地址,那么编译器也不能执行内联。 

          3. 虚函数不能为内联函数,因为内联函数是在编译期,而虚函数需要在运行期确定。

     

    最后,内联仅是对编译器的一个建议,编译器不会被强迫内联任何代码。

    三、静态对象的析构函数调用时机

    静态对象的析构函数在程序从main()中退出时,或标准C库函数exit()被调用时才会被调用。多数情况下,main()函数也是通过exit()来结束程序的。这意味着析构函数内部使用exit()是很危险的,因为这样将可能导致递归调用(VS2008中做了下试验,并没有发生递归调用,但是静态对象的析构的确是在调用exit的时候发生的)。但如果用标准的C库函数abort()来退出程序,静态对象的析构函数将不会被调用。

    可以用标准C库函数atexit()来制定当程序跳出main()时应当执行的操作。在这种情况下,在跳出main()或调用exit()之前,用atexit注册的函数可以在所有对象的析构函数之前被调用。

    以后要看的

    1. 标准C库函数atexit()

    2. 命名空间的使用

  • 相关阅读:
    三道趣味题目
    iOS开发中使用静态库 .a 文件
    java Graphics2D 画图
    堆和栈的区别
    iOS开发中KVC、KVO简介
    GPUImage的简单使用
    OC中 self.view.frame.size.height = 100; 不能通过编译的原因
    Xcode7 低版本iOS系统上下有黑边的问题
    c语言数组赋值
    ELF interpreter /libexec/ld-elf32.so.1 not found
  • 原文地址:https://www.cnblogs.com/hdtianfu/p/2293857.html
Copyright © 2011-2022 走看看