C++ 中placement new 操作符使用方法

C++ 中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;
}

执行结果:

[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;
}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • 全面解析C++中的new,operator new与placement new

    new operator/delete operator就是new和delete操作符,而operator new/operator delete是函数. new operator(1)调用operator new分配足够的空间,并调用相关对象的构造函数(2)不可以被重载 operator new(1)只分配所要求的空间,不调用相关对象的构造函数.当无法满足所要求分配的空间时,则        ->如果有new_handler,则调用new_handler,否则        ->如果没要求不

  • C++ 中placement new 操作符使用方法

    C++ 中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

  • kotlin代码中!!操作符的清楚方法

    前言 空安全是Kotlin中非常实用的特性,它能够让你避免许多隐藏的NullPointerExceptions问题.然而当你使用AS将Java代码转换成Kotlin代码后会出现很多的!! 操作符,因为出现!!意味着这里可能有未捕获的KotlinNullPointerException异常. 对于一个有强迫症的程序猿来说一个类中大篇幅的出现!! 绝对会使他们发疯的.幸运的是我们可以通过以下方式避免使用!!操作符. 1. 使用val代替var 我们都知道val修饰的变量是只读的,var修饰的变量是可

  • Smarty中常用变量操作符汇总

    本文汇总了Smarty中常用变量操作符,分享给大家供大家参考.具体如下: php模板引擎smarty的变量操作符可用于操作变量,自定义函数和字符. 语法中使用"|"应用变量操作符,多个参数用":"??指簟?/DIV> capitalize[首字母大写] count_characters[计算字符数] cat[连接字符串] count_paragraphs[计算段落数] count_sentences[计算句数] count_words[计算词数] date_f

  • JavaScript中关键字 in 的使用方法详解

    for-in循环应该用在非数组对象的遍历上,使用for-in进行循环也被称为"枚举". 对于数组 ,迭代出来的是数组元素 但不推荐,因为不能保证顺序,而且如果在Array的原型上添加了属性,这个属性也会被遍历出来,所以 最好数组使用正常的for循环,对象使用for-in循环 对于对象 ,迭代出来的是对象的属性: var obj = { "key1":"value1", "key2":"value2", &q

  • Ruby中对一元操作符重载实例

    一元操作大家都知道,就是表达式的操作符只有一个输入值.这个在C和Java中都很常见.今天我们要探讨一下Ruby中的一元操作符重载. 一元操作符有:+ – * ! & 等,为了避免与数值的 + – 混淆,重载一元操作符,要在后面加上一个 @ 操作符. 1. 一个简单的一元操作符重载例子:-@ 操作符 我们以String类为例子.String默认没有定义 – 操作符: 复制代码 代码如下: 1.9.3p125 :027 > a = "Hello" => "He

  • Lua中的元表与元方法学习总结

    前言 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了"+"符号,就可以进行类的加法运算.在Lua中也有这个道理,两个table类型的变量,你是无法直接进行"+"操作的,如果你定义了一个指定的函数,就可以进行了.那这篇博文就是主要讲的如何定义这个指定的函数,这个指定的函数是什么?希望对学习Lua的朋友有帮助. Lua是怎么做的? 通常,Lua中的每个值都有一套预定义的操作集合,比如数

  • 全面解析JavaScript中的valueOf与toString方法(推荐)

    可以这样说,所有JS数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题.在程序应用非常广泛.下面我们逐一来给大家介绍下. JavaScript 的 valueOf() 方法 valueOf() 方法可返回 Boolean 对象的原始值. 用法booleanObject.valueOf(),返回值为booleanObject 的原始布尔值.如果调用该方法的对象不是 Boolean,则抛出异常 TypeError. <script

  • Python3 操作符重载方法示例

    基础知识 实际上,"运算符重载"只是意味着在类方法中拦截内置的操作--当类的实例出现在内置操作中,Python自动调用你的方法,并且你的方法的返回值变成了相应操作的结果.以下是对重载的关键概念的复习: 运算符重载让类拦截常规的Python运算. 类可重载所有Python表达式运算符 类可以重载打印.函数调用.属性点号运算等内置运算 重载使类实例的行为像内置类型. 重载是通过特殊名称的类方法来实现的. 换句话说,当类中提供了某个特殊名称的方法,在该类的实例出现在它们相关的表达式时,Pyt

  • 详解Vue中的scoped及穿透方法

    scoped的由来 css一直有个令人困扰的作用域问题:即使是模块化编程下,在对应的模块的js中import css进来,这个css仍然是全局的.为了避免css样式之间的污染,vue中引入了scoped这个概念. 在vue文件中的style标签上,有一个特殊的属性:scoped.当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件.通过设置该属性,使得组件之间的样式不互相污染.如果一个项目中的所有style标签全部加上了scoped,相当于实现了样式的模块化. 但是这

  • Python 中字符串拼接的多种方法

    python拼接字符串一般有以下几种方法: ①直接通过(+)操作符拼接 s = 'Hello'+' '+'World'+'!' print(s) 输出结果: Hello World! 使用这种方式进行字符串连接的操作效率低下,因为python中使用 + 拼接两个字符串时会生成一个新的字符串,生成新的字符串就需要重新申请内存,当拼接字符串较多时自然会影响效率. ②通过str.join()方法拼接 strlist=['Hello',' ','World','!'] print(''.join(str

随机推荐