zoukankan      html  css  js  c++  java
  • Cpp Chapter 9: Memory Models and Namespaces Part3

    9.2.10 Storage schemes and dynamic allocation

    Memory allocated by new operator is called dynamic memory. Dynamic memory is controlled by new and delete operators rather than scope and linkage rules.
    Typically, the compiler has three separate memory chunks: one for static variables, one for automatic variables, one for dynamic storage.
    Suppose you write this:

    float * p_fees = new float [20];
    

    the p_fees pointer still follows the rules of scope and linkage, so you pass the address to another function when using it.
    Memory allocated by new typically is freed when the program terminates. However, the best practice is to use delete to free the memory allocated by new.

    Initialization with the new operator

    in C++11,for built-in types of C++ such as int and double, you use parentheses or braces enclosing the initialization value after the definition:

    int * pi = new int (6);
    double * pd = new double {99.99};
    

    However, for structure or array, only braces are allowed:

    struct where {double x; double y; double z;};
    where * one = new where {2.5, 5.3, 7.2};
    int * ar = new int [4] {2,4,6,7};
    

    For classes with suitable constructors, use parentheses(discussed later).

    When new fails

    When new can't find the requested amount of memory, it throws a std::bad_alloc exception.(discussed later)

    new: Operators, functions, and replacement functions

    new and delete operator call upon two functions:

    void * operator new(std::size_t);
    void * operator new[](std::size_t);
    void operator delete(void *)
    void operator delete[](void *);
    

    std::size_t is a typedef for some suitable integer type.(?) The functions above are collectivly termed allocation functions.

    The placement new operator

    Placement new operator allows you to specify the location to be used. Remember to include header file new when using placement new operator. An example of simple use of placement new operator:

    #include <new>
    struct chaff
    {
        char dross[20];
        int slag;
    };
    char buffer1[50];
    char buffer2[500];
    int main()
    {
        chaff * p1, *p2;
        int *p3, *p4;
        p1 = new chaff;
        p3 = new int[20];
        p2 = new (buffer1) chaff; // allocate p2's content in buffer1
        p4 = new (buffer2) int[20]; // allocate p4's content in buffer2
    }
    

    This code fragment shows the usage of placement new operator. p2 = new (place_supposed) thing; In the example, place_supposed could be an array. An example below:

    // newplace.cpp -- using placement new
    #include <iostream>
    #include <new>
    const int BUF = 512;
    const int N = 5;
    char buffer[BUF];
    int main()
    {
        using namespace std;
        double *pd1, *pd2;
        int i;
        cout << "Calling new and placement new:
    ";
        pd1 = new double[N];
        pd2 = new (buffer) double[N]; // 111111111111111
        for (i = 0; i < N; i++)
            pd2[i] = pd1[i] = 1000 + 20.0 * i;
        cout << "Memory addresses:
    " << "  heap: " << pd1 << "  static: " << (void *) buffer << endl;
        cout << "Memory contents:
    ";
        for (i = 0; i < N; i++)
        {
            cout << pd1[i] << " at " << &pd1[i] << "; ";
            cout << pd2[i] << " at " << &pd2[i] << endl;
        }
    
        cout << "
    Calling new and placement new a second time:
    ";
        double *pd3, *pd4;
        pd3 = new double[N];
        pd4 = new (buffer) double[N]; // 2222222222222
        for (i = 0; i < N; i++)
            pd4[i] = pd3[i] = 1000 + 40.0 * i;
        cout << "Memory contents:
    ";
        for (int i = 0; i < N; i++)
        {
            cout << pd3[i] << " at " << &pd3[i] << "; ";
            cout << pd4[i] << " at " << &pd4[i] << endl;
        }
    
        cout << "
    Calling new and placement new a third time:
    ";
        delete [] pd1;
        pd1 = new double[N];
        pd2 = new (buffer + N * sizeof(double)) double[N]; // 3333333333
        for (i = 0; i < N; i++)
            pd2[i] = pd1[i] = 1000 + 60 * i;
        cout << "Memory contents:
    ";
        for (i = 0; i < N; i++)
        {
            cout << pd1[i] << " at " << &pd1[i] << "; ";
            cout << pd2[i] << " at " << &pd2[i] << endl;
        }
        delete [] pd1;
        delete [] pd3;
        return 0;
    }
    

    This example illustrates 3 facts:

    1. Placement new indeed places the array in the buffer
    2. Placement new simply use the address passed to it. So it might overwrite past data(shown in the code with 11111111 and 2222222222). This feature is also illustrated that in code with 333333333, it uses a new chunk of memory instead of overwriting the previous, due to the fact that address "buffer + N * sizeof(double)" is passed to the placement new.
    3. When you delete a memory allocated by regular new, next new operator will reuse the memory. And, you can't apply delete to replacement new because the memory used by replacement new is predefined, which in this case is buffer, which is undeletable. Applying delete to replacement new will cause runtime error.
      Noteworthy is that using delete to regular new will free the entire block
  • 相关阅读:
    定义扩展点,实现发布订阅机制
    JS阻止事件冒泡
    Virtualbox安装黑苹果
    外部Tomcat使用Java热部署利器JRebel
    在Windows server 2016上使用docker
    Tomcat加载web.xml文件的顺序详解
    IDEA反编译整个jar包
    java集合类的继承结构
    利用BodyTagSupport创建带标签体的自定义标签
    jquery实现简单弹出框
  • 原文地址:https://www.cnblogs.com/fsbblogs/p/9746041.html
Copyright © 2011-2022 走看看