zoukankan      html  css  js  c++  java
  • placement new 操作符

    placement new操作符能够在分配内存时指定内存位置。下面的程序使用了placement new操作符和常规new操作符给对象分配内存。

    // placenew.cpp -- new, placement new, no delete
    #include <iostream>
    #include <string>
    #include <new>
    
    using namespace std;
    const int BUF = 512;
    
    class JustTesting
    {
    private:
        string words;
        int number;
    public:
        JustTesting(const string &s = "Just Testing", int n = 0)
        {
            words = s; number = n; cout << words << " constructed
    ";
        }
        ~JustTesting() { cout << words << " destroyed
    "; }
        void Show() const { cout << words << ", " << number << endl; }
    };
    
    int main(void)
    {
        char *buffer = new char [BUF];    // get a block of memory
        JustTesting *pc1, *pc2;
    
        pc1 = new (buffer)JustTesting;    // place object in buffer
        pc2 = new JustTesting("heap1", 20);    // place object on heap
    
        cout << "Memory block address:
    " << "buffer: "
            << (void *)buffer << "    heap: " << pc2 << endl;
        cout << "Memory contents: 
    ";
        cout << pc1 << ": ";
        pc1->Show();
        cout << pc2 << ": ";
        pc2->Show();
    
        JustTesting *pc3, *pc4;
        pc3 = new (buffer) JustTesting("bad Idea", 6);
        pc4 = new JustTesting("Heap2", 10);
    
        cout << "Memory contents: 
    ";
        cout << pc3 << ": ";
        pc3->Show();
        cout << pc4 << ": ";
        pc4->Show();
    
        delete pc2;    // free heap1
        delete pc4;    // free heap2
        delete [] buffer;    // free buffer
        cout << "Done
    ";
    
        return 0;
    }

    执行结果:

    [root@localhost 桌面]# ./new 
    Just Testing constructed
    heap1 constructed
    Memory block address:
    buffer: 0x936a008    heap: 0x936a248
    Memory contents: 
    0x936a008: Just Testing, 0
    0x936a248: heap1, 20
    bad Idea constructed
    Heap2 constructed
    Memory contents: 
    0x936a008: bad Idea, 6
    0x936a290: Heap2, 10
    heap1 destroyed
    Heap2 destroyed
    Done

    上面的程序使用placement new操作时存在两个问题。首先,在创建第二个对象时,placement new操作符使用一个新对象来覆盖用于第一个对象的内存单元。显然,如果类动态地为其成员分配内存,这将引发问题。

         其次,将delete用于pc2和pc4时,将自动调用为pc2和pc4指向的对象调用析构函数;然而,将delete[]用于buffer时,不会为使用布局new操作符创建的对象调用析构函数。

       为确定两个单元不重叠,可以这样做:

    pc1 = new (buffer) JustTesting;
    pc3 = new (buffer + sizeof(JustTesting)) JustTesting("Better Idea", 6);

     其中指针pc3相对于pc1的偏移量为JustTesting对象的大小

      第二个教训是,如果使用placement new操作符来为对象分配内存,必须确保其析构函数被调用,但如何确保呢?

      例如,在堆中创建的对象,可以这样做:

    delete pc2;

    然而,对于使用placement new操作符创建的对象,不能像下面一样调用delete

    delete pc1; // NO!!!

      原因在于delete可与常规new操作符配合使用,但不能与placement new操作符配合使用。

    那么我们要显示调用析构函数,必须指定要销毁的对象:

    pc3->~JustTesting();   // destroy object pointed to by pc3

    int main(void)
    {
        char *buffer = new char[BUF];    // get a block of memory
        JustTesting *pc1, *pc2;
    
        pc1 = new (buffer) JustTesting;    // place object in buffer
        pc2 = new JustTesting("Heap1", 20);    // place object on heap
    
        cout << "Memory block addresses: /n" << "buffer: "
            << (void *)buffer << "    heap: " << pc2 << endl;
        cout << "Memory contents: ";
        cout << pc1 << ": ";
        pc1->Show();
        cout << pc2 << ": ";
        pc2->Show();
    
        JustTesting *pc3, *pc4;
        // fix placement new location
        pc3 = new (buffer + sizeof(JustTesting)) JustTesting("better Idea", 6);
        pc4 = new JustTesting("Heap2", 10);
    
        cout << "Memory contents: ";
        cout << pc3 << ": ";
        pc3->Show();
        cout << pc4 << ": ";
        pc4->Show();
    
        delete pc2;        // free heap1
        delete pc4;        // free heap2
        // explicitly destroy placement new object
        pc3->~JustTesting();    // destroy object pointed to by pc3
        pc1->~JustTesting();    // destroy object pointed to by pc1
        delete []buffer;    // free buffer
        cout << "Done/n";
    
        return 0;
    }
  • 相关阅读:
    修改git提交的用户名和密码
    并发编程大师系列之:wait/notify/notifyAll/condition
    并发编程大师系列之:Synchronized的类锁和对象锁
    并发编程大师系列之:线程的定义和中断 interrupt
    SpringBoot项目mysql配置文件密码加密(jasypt)
    Linux下安装nginx实现伪分布
    idea远程debug调试阿里云ECS
    使用docker简单启动springboot项目
    用Navicat连接阿里云ECS服务器上的MySQL数据库
    Linux下安装JDK1.8
  • 原文地址:https://www.cnblogs.com/wuchanming/p/4340268.html
Copyright © 2011-2022 走看看