• More Effective C++读书笔记(二)


    1、不要试图重载||,&&操作符,因为它们使用短路求值法(一旦确定了布尔表达式的真假值,即使还有部分表达式没有被测试,布尔表达式也停止运算),而重载之后采用的是函数调用法。首先当函数被调用时,需要运算其所有参数,所以调用函数functions operator&& 和 operator||时,两个参数都需要计算,换言之,没有采用短路计算法。第二是C++语言规范没有定义函数参数的计算顺序,所以没有办法知道表达式1与表达式2哪一个先计算。完全可能与具有从左参数到右参数计算顺序的短路计算法相反。同样,也不要试图重载逗号(,)操作符,因为一个包含逗号的表达式首先计算逗号左边的表达式,然后计算逗号右边的表达式,整个表达式的结果是逗号右边表达式的值,这也可能和函数调用法对参数的计算顺序不同。因为重载操作符很重要的一点就是要重载之后行为特性与其被料想(缺省的行为特征)的一样。否则,重载是完全轻率的行为。C++规定不能重载的操作符有., .*, ::, ?:,new, delete, sizeof, typeid,static_cast, dynamic_cast, const_cast, reinterpret_cast

    2、理解各种不同含义的new和delete(new操作符和operator new操作),先分析一段代码:
    string *ps = new string("Memory Management");
    使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。
    它要完成的功能分成两部分:第一部分是分配足够的内存以便容纳所需类型的对象。第二部分是它调用构造函数初始化内存中的对象。new操作符总是做这两件事情,你不能以任何方式改变它的行为(不能重载)。
    完成new操作符功能的第一部分分配内存所调用函数的名字是operator new(可以重载)。
    函数operator new 通常这样声明:
    void * operator new(size_t size);
    返回值类型是void*,因为这个函数返回一个未经处理(raw)的指针,未初始化的内存。参数size_t确定分配多少内存。你能增加额外的参数重载函数operator new,但是第一个参数类型必须是size_t。operator new的职责只是分配内存(返回一个void *指针,有点类似C语言的malloc)。它对构造函数一无所知。
    当你的编译器遇见这样的语句:
    string *ps = new string("Memory Management");
    它生成的代码或多或少与下面的代码(伪码)相似:
    void *memory = operator new(sizeof(string)); // 得到未经处理的内存
    call string::string("Memory Management") on *memory;// 为String对象初始化
    string *ps = static_cast<string*>(memory); //内存中的对象是ps指针指向新的对象

    同样,我们分析定位new操作符,例如:
    new (buffer) Widget(widgetSize)
    当该定位new操作符隐含调用operator new函数时,把这个变量(内存地址buffer)传递给它。被调用的operator new函数除了待有强制的参数size_t外,还必须接受void*指针参数,指向构造对象占用的内存空间。这个operator new就是placement new,它看上去象这样:
    void * operator new(size_t, void *location)
    {
    return location;
    }
    总结:
    如果想在堆上建立一个对象,应该用new操作符。它既分配内存又为对象调用构造函数。如果你仅仅想分配内存,就应该调用operator new函数;它不会调用构造函数。如果你想定制自己的在堆对象被建立时的内存分配过程,你应该写你自己的operator new函数,然后使用new操作符,new操作符会调用你定制的operator new。如果你想在一块已经获得指针的内存里建立一个对象,应该用placement new。

    对于delete和operator delete也有类似的结论:
    delete 先调用析构函数,然后调用operator delete释放内存,而operator delete仅仅是释放内存。如果你用placement new在内存中建立对象,你应该避免在该内存中用delete操作符。因为delete操作符调用operator delete来释放内存,但是包含对象的内存最初不是被operator new分配的,placement new只是返回转递给它的指针。谁知道这个指针来自何方?而你应该显式调用对象的析构函数来解除构造函数的影响。


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/digu/archive/2007/11/13/1882023.aspx

  • 相关阅读:
    Vue23 ref属性
    Vue27 scoped样式
    Vue 24 props
    Vue21 组件
    Vue25 mixin
    Vue29 自定义事件及消息总线
    Vue28 Web Storage
    AcWing2022寒假每日一题(1 月 2 日 ~ 1 月 15 日)
    leetcode 206. Reverse Linked List 反转链表(简单)
    leetcode 647. Palindromic Substrings回文子串(中等)
  • 原文地址:https://www.cnblogs.com/lancidie/p/1952536.html
Copyright © 2020-2023  润新知