一、定义

1、new

new是c++中的关键字,,其行为总是一致的。它先调用operator new分配内存,然后调用构造函数初始化那段内存。

new 操作符的执行过程:
1. 调用operator new分配内存 ;
2. 调用构造函数在operator new返回的内存地址处生成类对象;

2、operator new

operator new是一个函数,就像重载任何一个符号如operator +,它用来分配内存(只不过new除了调用它还有其他步骤)。它可以被重载,通过重载它,可以改变new操作符的功能。它的功能介意类比c语言中的malloc,如果类中没有重载operator new,那么调用的就是全局的::operator new来从堆中分配内存。

2、placement new

placement new 是c++中对operator new 的一个标准、全局的重载版本。它并不分配内存,只是返回指向已经分配好的某段内存的一个指针,placement new允许你在一个已经分配好的内存中(栈或者堆中)构造一个新的对象。

二、使用方法

1、new的使用

在堆上分配分配一块内存

struct A* i0 = new A;
struct A* i1 = new A();

看new的原型:

void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
__attribute__((__externally_visible__));
void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc)
__attribute__((__externally_visible__));
void operator delete(void*) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));
void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
__attribute__((__externally_visible__));

发现它有一个参数,size_t,表示前面调用placement new分配的内存大小,new接下来会在这块内存中调用构造函数,new的操作也是c++来保证的。

2、operator new的使用

分配8个字节的内存,因为是未重载,所以这里调用的是全局operator new,从堆上分配了8个字节

void* i = operator new ();

如果想重载operator new需要注意以下几点:

(1)重载时,返回类型必须声明为void*

(2)重载时,第一个参数类型必须为表达要求分配空间的大小(字节),类型为size_t

(3)重载时,可以带其它参数

(4)分配函数为类成员函数或全局函数;如果分配函数在全局范围之外的名称空间范围中声明,或者在全局范围中声明为静态,则程序是病态的

比如下面的例子中,在A重载了operator new打印出tag,返回全局的opereator new,然后在main函数中调用A的重载版本。

struct A{
int a;
char b;
void* operator new(size_t size,int tag) throw(){
cout << tag << endl;
return ::operator new(size);
}
}; int main()
{
void* i = A::operator new (,);
cout << i << endl; return ;
}

最终结果即分配了内存,又打印出了tag的值

如果我们重载全局的operator new函数,然后调用new,则new的操作也会被更改,比如下面的例子(这个例子的operator new只有一个参数)

struct A{
int a;
char b;
};
void* operator new(size_t num) throw(){
cout << num << endl;
return nullptr;
} int main()
{
A* i = new A;
cout << i << endl; return ;
}

最终的结果是

可以看出,虽然没有直接调用operator new,但是new的操作已经被更改了。

还需要关注一个小地方,就是operator new调用时的参数和new的参数是有所区别的。new在调用的时候会忽略第一个size_t的参数,但是如果直接调用operator new来进行内存分配的时候是需要这个参数的。

也就是本节的第二个例子如果operator new的定义要像本节的第一个例子有两个参数的话,对new的调用应该如下:

A* i = new() A ;

3、placement new的使用

placement new是c++实现的operator new版本,它的实现如下

// Default placement versions of operator new.
inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }
inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; } // Default placement versions of operator delete.
inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT { }
inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { }
//@}

可以看到实际上它就返回了传进来的地址,根据operator的第二个例子,通过重载全局的operator new之后,new函数的操作就被改变了。也就能猜出,在调用new的时候参数需要加上一个地址,placement new的功能就是在这个地址之上进行构造。

placement new的使用步骤如下

1)分配内存

char* buff = new char[ sizeof(Foo) * N ];
memset( buff, , sizeof(Foo)*N );

2)构建对象

Foo* pfoo = new (buff)Foo;

3)使用对象

pfoo->print();
pfoo->set_f(1.0f);
pfoo->get_f();

4)析构对象,显式的调用类的析构函数。

pfoo->~Foo();

5)销毁内存

delete [] buff;

上面5个步骤是标准的placement new的使用方法。

c++中的new、operator new、placement new的更多相关文章

  1. c++中new/operator new/placement new

    1. new/delete c++中的new(和对应的delete)是对堆内存进行申请和释放,且两个都不能被重载. 2. operator new/operator delete c++中如果想要实现 ...

  2. C++中的new,operator new与placement new

    以下是C++中的new,operator new与placement new进行了详细的说明介绍,需要的朋友可以过来参考下     new operator/delete operator就是new和 ...

  3. C++内存管理(new operator/operator new/operator delete/placement new)

    new operator 我们平时使用的new是new操作符(new operator),就像sizeof一样是语言内置的,不能改变它的含义,功能也是一样的 比如: string *ps = new ...

  4. 【转】C++易混知识点3. New Operator, Operator New, Placement New 实例分析,比较区别

    我们知道,C++中引入了New 这个内置符号,很大方便了指针的使用,程序员不必关注与这块堆上新分配的内存是如何来的,如何初始化的,然后如何转换为我们想要的类型指针的.现在,我们重点来分析下这个NEW内 ...

  5. [译]Javascript中的Ternary operator

    本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...

  6. C++中的定位放置new(placement new)

    一般来说,使用new申请空间时,是从系统的“堆”(heap)中分配空间.申请所得的空间的位置时根据当时的内存的实际使用情况决定的.但是,在某些特殊情况下,可能需要在程序员指定的特定内存创建对象,这就是 ...

  7. 对于C++中const & T operator= 的一点思考

    一个正常的assignment操作符的声明是这样的. const elmentType & elmentType::operator=(const elmentType &rhs) 这 ...

  8. C++中的new、operator new与placement new

    转:http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html new/delete与operator new/operator ...

  9. new 、operator new 和 placement new

    一.原生operator new 我们先从原生operator new开始.考虑如下代码,它用来分配5个int型的空间并返回指向他们的指针[1]: int* v = static_cast<in ...

随机推荐

  1. 计算机网络三:域名、IP地址和TCP/IP协议

    一.域名        域名(Domain Name),简称域名.网域,是由一串用点分隔的字符型标志名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时 ...

  2. python set所用后列表不改变里面内容排序

    my_list = [1,2,1,54,5,64,4681,4,676] my_list_two = list(set(my_list)) my_list_two.sort(key = my_list ...

  3. 下载、安装JDK并配置JDK的环境变量

    概念简介: JDK:(Java Development Kit)Java语言的软件开发工具包,它包含了Java程序的开发工具和Java程序的运行环境JRE: JRE:(Java Runtime Env ...

  4. UltraISO制作CentOS 7.6 U盘引导安装盘

    一.制作准备: 1.UltraISO下载安装 2.CentOS镜像文件下载(阿里镜像下载) 二.制作引导盘: 1.电脑插入U盘 2.UltraISO加载镜像文件: 文件->打开->选择对应 ...

  5. mysql5.6版本的优化

    1. 目标 l 了解什么是优化 l 掌握优化查询的方法 l 掌握优化数据库结构的方法 l 掌握优化MySQL服务器的方法 2. 什么是优化? l 合理安排资源.调整系统参数使MySQL运行更快.更节省 ...

  6. [转] Snapshotting with libvirt for qcow2 images

    http://kashyapc.com/2011/10/04/snapshotting-with-libvirt-for-qcow2-images/ Libvirt 0.9.6 was recentl ...

  7. Project Structure详解

    Project Structure “ 项目结构”对话框允许您管理项目和IDE级别的元素,例如Modules,Facets,Libraries, Artifacts和SDK. 在大多数情况下,左边部分 ...

  8. 数值计算 的bug:(理论)数学上等价,实际运行未必等价

    1. 计算表达式的值(lambda 表达式) fun1 和 fun2 理论上是等价的:同样的输入情形下,两种输出结果不一致. # fun1 定义 fun1=lambda x:sqrt(x+1)-sqr ...

  9. C#轻量级通通讯组件StriveEngine —— C/S通信开源demo(2) —— 使用二进制协议 (附源码)

    前段时间,有几个研究ESFramework通信框架的朋友对我说,ESFramework有点庞大,对于他们目前的项目来说有点“杀鸡用牛刀”的意思,因为他们的项目不需要文件传送.不需要P2P.不存在好友关 ...

  10. 脑残式网络编程入门(四):快速理解HTTP/2的服务器推送(Server Push)

    本文原作者阮一峰,作者博客:ruanyifeng.com. 1.前言 新一代HTTP/2 协议的主要目的是为了提高网页性能(有关HTTP/2的介绍,请见<从HTTP/0.9到HTTP/2:一文读 ...