博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++中new的用法
阅读量:5342 次
发布时间:2019-06-15

本文共 3144 字,大约阅读时间需要 10 分钟。

new operator

经常使用的T *ptr = new T(),分配内存,调用构造函数

  1. 调用operator new分配内存,operator new (sizeof(A)) 
  2. 调用构造函数生成类对象,A::A() 
  3. 返回相应指针 

事实上,分配内存这一操作就是由operator new(size_t)来完成的,如果类A重载了operator new,那么将调用A::operator new(size_t ),否则调用全局::operator new(size_t ),后者由C++默认提供。

operator new

(1) void* operator new (std::size_t size);(2) void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) noexcept;(3) void* operator new (std::size_t size, void* ptr) noexcept;
  1. 分配size字节的存储空间,如果成功的话返回一个非空指针,将对象类型进行内存对齐,指向分配空间第一个字节。如果失败的话,会抛出bad_alloc异常,不调用构造函数
  2. 和第一种一样,差别在于,如果失败的话,不抛出异常,而是返回一个null指针,不调用构造函数
  3. 只是返回ptr指针,并不分配内存空间。这里的ptr应该指向先前已经分配好的空间,这里的new调用对象的构造函数,在ptr指向的内存空间构造对象或对象数组。ptr指向的内存只要不释放,可以重复使用,所以这种用法一般在对象池或内存池实现中使用也就是placement new版本
#include 
#include
using namespace std;struct A{ A( bool xpt ) { if( xpt ) throw( xpt ); } void *operator new(size_t size) { cout<<"operator new"<

在分配失败的情况下,抛出异常std::bad_alloc而不是返回NULL,因此通过判断返回值是否为NULL是徒劳的。

placement new

  1.这种new允许在一块已经分配成功的内存上重新构造对象或对象数组。placement new不用担心内存分配失败,因为它根本不分配内存,它做的唯一一件事情就是调用对象的构造函数

  2.用定位放置new操作,既可以在栈(stack)上生成对象,也可以在堆(heap)上生成对象。

  3.使用语句A* p=new (mem) A;定位生成对象时,指针p和数组名mem指向同一片存储区。 会自动调用类A的构造函数,但是由于对象的空间不会自动释放(对象实际上是借用别人的空间),所以必须显示的调用类的析构函数,如本例中的p->~A()。 

  4.如果有这样一个场景,我们需要大量的申请一块类似的内存空间,然后又释放掉,比如在在一个server中对于客户端的请求,每个客户端的每一次上行数据我们都需要为此申请一块内存,当我们处理完请求给客户端下行回复时释放掉该内存,表面上看者符合c++的内存管理要求,没有什么错误,但是仔细想想很不合理,为什么我们每个请求都要重新申请一块内存呢,要知道每一次内从的申请,系统都要在内存中找到一块合适大小的连续的内存空间,这个过程是很慢的(相对而言),极端情况下,如果当前系统中有大量的内存碎片,并且我们申请的空间很大,甚至有可能失败。为什么我们不能共用一块我们事先准备好的内存呢?可以的,我们可以使用placement new来构造对象,那么就会在我们指定的内存空间中构造对象。 

void* operator new (std::size_t size, void* ptr) noexcept;

placement new构造起来的对象或其数组,要显示的调用他们的析构函数来销毁,千万不要使用delete ,要显式调用它们的析构函数来销毁(析构函数并不释放对象的内存),千万不要使用delete.这是因为placement new构造起来的对象或数组大小并不一定等于原来分配的内存大小,使用delete会造成内存泄漏或者之后释放内存时出现运行时错误。

#include 
#include
#include
using namespace std;struct A{ char c; int i; short a;}; int main(){ A *a1=new A; A *a2=new(a1) A;//再堆上构造对象 char *c={
"fdsafk"};//在栈上构造对象 cout<<(void *)c<

 

  当使用new运算符定义一个多维数组变量或数组对象时,它产生一个指向数组第一个元素的指针,返回的类型保持了除最左边维数外的所有维数。例如:  

int *p1 = new int[10];

  返回的是一个指向int的指针int*  

int (*p2)[10] = new int[2][10];

  new了一个二维数组, 去掉最左边那一维[2], 剩下int[10], 所以返回的是一个指向int[10]这种一维数组的指针int (*)[10].  

  int (*p3)[2][10] = new int[5][2][10];  new了一个三维数组, 去掉最左边那一维[5], 还有int[2][10], 所以返回的是一个指向二维数组int[2][10]这种类型的指针int (*)[2][10].     

#include
#include
using namespace std;int main() { int *a = new int[34]; int *b = new int[]; int (*c)[2]=new int[][2];//指针 int[34][2]; int (*d)[2] = new int[][2]; //指针 int (*e)[2][3] = new int[34][2][3]; int (*f)[2][3] = new int[][2][3];//指针 a[0] = 1; b[0] = 1; //运行时错误,无分配的内存,b只起指针的作用,用来指向相应的数据 c[0][0] = 1; d[0][0] = 1;//运行时错误,无分配的内存,d只起指针的作用,用来指向相应的数据 e[0][0][0] = 1; f[0][0][0] = 1;//运行时错误,无分配的内存,f只起指针的作用,用来指向相应的数据 cout<
<

输出结果:

 int *

int *

int (*)[2]

int (*)[2]

int (*)[2][3]

int (*)[2][3]

转载于:https://www.cnblogs.com/tianzeng/p/8964215.html

你可能感兴趣的文章
浅谈C语言中的联合体
查看>>
Photoshop独立安装包下载页面
查看>>
使用git获取远程分支
查看>>
.Net开发之Request处理
查看>>
看了才知道!伊朗黑客组织原来这么牛
查看>>
杂七杂八的一些板子
查看>>
读入优化模板
查看>>
linux 查看网络流量命令
查看>>
十分钟读懂:Java并发——CSP模型
查看>>
d3 选择器
查看>>
javascript基础学习七
查看>>
C#环境datagidview添加删除操作
查看>>
shell脚本之awk、sed、grep案例
查看>>
Redis 详解 (三) redis的五大数据类型详细用法
查看>>
MBProgressHUD 显示后,为何不能点击屏幕其他地方
查看>>
警惕!面部识别技术正在开始构成重大隐私威胁
查看>>
关于Git的一些操作记录
查看>>
Google的开源C++单元测试框架Google Test
查看>>
Qt Installer Framework 使用说明(三)
查看>>
Memory Map
查看>>