C++定位new用法及注意事项

news/2024/12/29 8:33:01/
使用定位new创建对象,显式调用析构函数是必须的,这是析构函数必须被显式调用的少数情形之一!,
另有一点!!!析构函数的调用必须与对象的构造顺序相反!切记!!!
定位new的使用格式:
1.new (place_address) type
2.new (palce_address) type (initializer_list)
其中place_address必须是一个指针,initializer_list是type类型的初始化列表

使用请看下面的代码例程

#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" << endl;}~JustTesting() { cout << words << " destroyed!" << endl; }void Show()const { cout << words << " , " << number << endl; }
};int main() {char* buffer = new char[BUF];//常规new在堆上申请空间cout << "\nMemory block address:\n" << "buffer: " << (void*)buffer<< "\n****************************************\n";JustTesting* pc1, * pc2;pc1 = new (buffer) JustTesting;//定位newpc2 = new JustTesting("Heap1", 20);//常规newcout << "\nMemory contents:" << endl;cout << pc1 << ": ";pc1->Show();cout << pc2 << ": ";pc2->Show();cout << "----------------------------------------\n";JustTesting* pc3, * pc4;pc3 = new (buffer)JustTesting("Bad Idea", 6);//定位newpc4 = new JustTesting("Heap2", 10);//常规newcout << "\nMemory contents:" << endl;cout << pc3 << ": ";pc3->Show();cout << pc4 << ": ";pc4->Show();delete pc2;//释放pc2申请的空间delete pc4;//释放pc4申请的空间delete[] buffer;//释放buffer指向的空间,但是这里并没有调用其析构函数//pc3->~JustTesting(); //需要显式调用构造函数//pc1->~JustTesting();cout << "Done!" << endl;return 0;
}

执行结果如下:

结果分析: 

1.使用定位new创建的对象的地址与内存缓冲区地址一致,说明定位new并没有申请新空间,而构造函数的调用说明定位new的确调用了构造函数。
2.在使用delete回收空间时,可以发现并未回收pc1与pc3,其原因在于pc1与pc3指向的对象位于内存缓冲区,该空间并不是定位new申请,而是常规new申请的,因此我们需要delete[]回收内存缓冲区,而不是delete pc1与delete pc3
3.pc1与pc3一致,说明第一个对象被第三个覆盖!显然,如果类动态地为其成员分配内存,这将引发问题!,所以,当我们使用定位new创建对象必须自己保证不会覆盖任何不想丢失的数据!,就这个例程而言,避免覆盖,最简单的做法如下:pc1 = new (buffer) JustTesting;pc3 = new (buffer + sizeof(JustTesting)) JustTesting("Better Idea!",6);
4.delete[] buffer并未引发对象的析构!,虽然对象1及3的空间被回收,但对象1与3并未析构!这一点将时刻提醒我们使用定位new需要自己显式调用析构函数,完成对象的析构!,但该析构并不能通过delete pc1或delete pc3实现!(因为delete与定位new不能配合使用!,否则会引发运行时错误!),只能通过显式析构,如下:pc3->~JustTesting();pc1->~JustTesting();

http://www.ppmy.cn/news/24386.html

相关文章

C语言柔性数组

目录什么是柔性数组柔性数组的使用什么是柔性数组 柔性数组是在C99中定义的 结构体的最后一个元素允许是未知大小的数组&#xff0c;这就叫柔性书组 柔性数组的长度可以写成0&#xff0c;也可以不规定数组长度 下面两种写法都是正确的 struct S { int i; int a[0];//柔性数…

链表OJ(一)

目录 从尾到头打印链表_牛客题霸_牛客网 160. 相交链表 141. 环形链表 142. 环形链表 II 138. 复制带随机指针的链表 从尾到头打印链表_牛客题霸_牛客网 输入一个链表的头节点&#xff0c;按链表从尾到头的顺序返回每个节点的值&#xff08;用数组返回&#xff09;。 如输入…

【LeetCode第 332 场周赛】

传送门 文章目录6354. 找出数组的串联值6355. 统计公平数对的数目6356. 子字符串异或查询6357. 最少得分子序列6354. 找出数组的串联值 题目 思路 前后指针 代码 class Solution { public:long long findTheArrayConcVal(vector<int>& nums) {long long res 0;i…

千锋教育嵌入式物联网教程之系统编程篇学习-03

目录 进程的终止 exit函数 _exit函数 进程退出清理 进程间的替换 进程间通信 常见通信机制 进程间通信的实质 信号 产生信号的方式 信号的默认处理方式 进程对信号的处理方式 kill函数 进程的终止 使用exit函数对进程进行终止&#xff0c;而return只是结束函数&a…

Java围棋游戏的设计与实现

技术&#xff1a;Java等摘要&#xff1a;围棋作为一个棋类竞技运动&#xff0c;在民间十分流行&#xff0c;为了熟悉五子棋规则及技巧&#xff0c;以及研究简单的人工智能&#xff0c;决定用Java开发五子棋游戏。主要完成了人机对战和玩家之间联网对战2个功能。网络连接部分为S…

【PTA Advanced】1060 Are They Equal(C++)

目录 题目 Input Specification: Output Specification: Sample Input 1: Sample Output 1: Sample Input 2: Sample Output 2: 思路 C 知识点UP 代码 题目 If a machine can save only 3 significant digits, the float numbers 12300 and 12358.9 are considered …

MWORKS--MoHub介绍

MWORKS--MoHub介绍1 介绍1.1 简介1.2 功能特征2 快速上手2.1 进入工作台2.2 新建仓库并进入建模空间2.3 建模进入建模工作空间加载模型库新建模型2.4 仿真2.5 后处理曲线、动画2.6 查看模型信息3 使用手册参考1 介绍 1.1 简介 MWORKS.MoHub 支持工业知识、经验、数据的模型化…

ajax是什么?咋实现的

创建交互式网页应用的网页开发技术 再不重新加载整个网页的前提下&#xff0c;与服务器交换数据并且更新部分内容 简单来说就是无页面刷新的数据交互 通过创建xmlhttprequest对象向服务器异步发送请求从而获取数据&#xff0c;然后操作dom更新内容 1&#xff0c;创建xmlhttpr…