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\n";
    }
    ~JustTesting() { cout << words << " destroyed\n"; }
    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:\n" << "buffer: "
        << (void *)buffer << "    heap: " << pc2 << endl;
    cout << "Memory contents: \n";
    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: \n";
    cout << pc3 << ": ";
    pc3->Show();
    cout << pc4 << ": ";
    pc4->Show();

    delete pc2;    // free heap1
    delete pc4;    // free heap2
    delete [] buffer;    // free buffer
    cout << "Done\n";

    return 0;
}

执行结果:

[[email protected] 桌面]# ./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;
}
时间: 2024-10-16 21:24:30

placement new 操作符的相关文章

C++中placement new操作符(经典)

参见下面两个博客 1. http://blog.csdn.net/zhangxinrun/article/details/5940019 placement new是重载operator new的一个标准.全局的版本,它不能被自定义的版本代替(不像普通的operator new和operator delete能够被替换成用户自定义的版本). 它的原型如下: void *operator new( size_t, void *p ) throw()  { return p; } 首先我们区分下几个

placement new操作符

acement new是operator new的一个重载版本,只是我们很少用到它.如果你想在已经分配的内存中创建一个对象,使用new是不行的.也就是说placement new允许你在一个已经分配好的内存中(栈或堆中)构造一个新的对象.原型中void*p实际上就是指向一个已经分配好的内存缓冲区的的首地址. 我们知道使用new操作符分配内存需要在堆中查找足够大的剩余空间,这个操作速度是很慢的,而且有可能出现无法分配内存的异常(空间不够).placement new就可以解决这个问题.我们构造对象

c++中的placement new操作符学习

参考文献:http://blog.csdn.net/zhangxinrun/article/details/5940019 new操作符: 例子如下:int * pint=new int(23):它先在堆上分配内存空间:接着初始化这个内存空间:最后返回此指针. 对于此操作是可以重载的,记住是只能在类中被重载,得到了一个重载版本为placement new (旧版本是operator new),原型如下void *operator new( size_t, void *p ) throw()  {

C++ 中 new 操作符内幕:new operator、operator new、placement new

原文链接 一.new 操作符(new operator) 人们有时好像喜欢有益使C++语言的术语难以理解.比方说new操作符(new operator)和operator new的差别. 当你写这种代码: string *ps = new string("Memory Management"); 你使用的new是new操作符. 这个操作符就象sizeof一样是语言内置的.你不能改变它的含义,它的功能总是一样的.它要完毕的功能分成两部分.第一部分是分配足够的内存以便容纳所需类型的对象.

c++ placement new概念

参考:http://www.cnblogs.com/Clingingboy/archive/2013/04/26/3044910.html 转:http://bbs.chinaunix.net/thread-1015707-1-1.html 问题:什么是“定位放置new(placement new)”,为什么要用它 ? 定位放置new(placement new)有很多作用.最简单的用处就是将对象 放置在内存中的特殊位置.这是依靠 new表达式部分的指针参数的位置来完成的: #include <

placement new的使用及好处

详细的介绍可以看这几篇文章: C++中placement new操作符(经典) Placement new的用法及用途 (转)遵循placement new的用法规范 归纳一下placement new的好处: 在已分配好的内存上进行对象的构建,构建速度快. 可以反复利用同一块已分配好的内存,有效的避免内存碎片问题. 建立对象数组时,能够调用带参数的构造函数. placement new的使用及好处

【转载】C++内存分配

原文:C++内存分配 内存泄露相信对C++程序员来说都不陌生.解决内存泄露的方案多种多样,大部分方案以追踪检测为主,这种方法实现起来容易,使用方便,也比较安全. 首先我们要确定这个模块的主要功能: 能追踪内存的分配和释放过程. 要能显示内存分配的相关信息,比如内存块大小,代码所在文件所在行等. 在发现内存泄露时及时给出相关信息. 能正确处理一些异常情况,比如内存不足,对象初始化失败等等. 是线程安全的.[*这个还没有实现] 有了一些基本功能需求,我们需要考虑每种功能怎么去实现.首先,我们可以通过

一个跨平台的 C++ 内存泄漏检测器

2004 年 3 月 01 日 内存泄漏对于C/C++程序员来说也可以算作是个永恒的话题了吧.在Windows下,MFC的一个很有用的功能就是能在程序运行结束时报告是否发生了内存泄漏.在Linux下,相对来说就没有那么容易使用的解决方案了:像mpatrol之类的现有工具,易用性.附加开销和性能都不是很理想.本文实现一个极易于使用.跨平台的C++内存泄漏检测器.并对相关的技术问题作一下探讨. 基本使用 对于下面这样的一个简单程序test.cpp: int main() { int* p1 = ne

Python爬取CSDN博客文章

之前解析出问题,刚刚看到,这次仔细审查了 0 url :http://blog.csdn.net/youyou1543724847/article/details/52818339Redis一点基础的东西目录 1.基础底层数据结构 2.windows下环境搭建 3.java里连接redis数据库 4.关于认证 5.redis高级功能总结1.基础底层数据结构1.1.简单动态字符串SDS定义: ...47分钟前1 url :http://blog.csdn.net/youyou1543724847/