理解各种不同含义的 new 和 delete

new operator  new操作符

operator new  操作符new

placement new  定位new

string *ps = new string("Memory Management"); 

这里的new是new 操作符。这里共有两个步骤的工作要做:

①为对象申请空间 ②调用构造函数初始化内存中的对象

new 操作符总是做这两件事,不可以任何方式改变其行为。

但是你可以改变步骤①如何为对象申请空间。

new 操作符是通过 operator new这个函数为对象申请空间。

operator new 的声明形式

void* operator new(size_t size);//在做其他形式重载时也要保证第一个参数必须为size_t类型

函数的返回值是 void*,参数size确定分配多少内存

该函数调用时与普通函数一样

ST *pt = operator new(sizeof(ST));

placement new的作用是在已经被分配但是尚未处理的(raw)内存中构造一个对象。它是一个特殊的operator new

void* operator new(size_t, void *p)//参数size_t没有名字,但是为了防止编译器警告必须加上
{
      return p;
}    

在使用placement new时调用者已经获得了指向内存的指针,因为调用者知道对象应该放在

哪里。placement new必须做的就是返回传递给它的指针。

总结:如果你想在堆上建立一个对象,应该使用new 操作符,它既分配内存又为对象调用构造函数;

   如果你只想分配内存,就调用operator new函数,它不会调用构造函数;

    如果你想定制自己的在堆对象被建立时的内存分配过程,你应该写自己的operator new 函数,然后使用

new操作符,new操作符会调用你定制的operator new。

   如果你想在一块已经获得指针的内存里建立一个对象,应该使用palcement new.

#include<iostream>
#include<vld.h>
using namespace std;
class ST
{
private:
    char *ptr;
public:
    ST(const char *str = ""):ptr("")
    {
        cout<<"Object was built. "<<endl;
        if(str == NULL)
        {
            this->ptr = new char[1];
            this->ptr[0] = ‘\0‘;
        }
        else
        {
            this->ptr = new char [strlen(str)+1];
            strcpy(ptr, str);
        }
    }
    ~ST()
    {
        cout<<"Object was free. "<<endl;
        delete []this->ptr;
        ptr = NULL;
    }
    void* operator new(size_t, void *p)//placement new
    {
        return p;
    }
    void operator delete(void *p)
    {
        cout<<"---"<<endl;
        free(p);
    }
};
void* operator new(size_t t)
{
    void *p = malloc(t);
    return p;
}void* operator new[](size_t t)
{
    void *p = malloc(t);
    return p;
}void operator delete[](void *p)
{
    cout<<"--[][]\n";
    free(p);
    return;
}
void main()
{
     ST *pt = (ST*)operator new (sizeof(ST)); //使用重载的operator new 为对象pt分配空间
     new(pt)ST("Hello");      //这里调用placement new,同时也调用了构造函数。前两行代码等价于在未重载new时 ST *pt = new ST("Hello");
     pt->~ST();           //通过pt指针可直接调用析构函数,但是不可调用构造函数
     operator delete (pt);    //调用operator delete函数 后行代码等价于在未重载delete时 delete pt

运行结果

为了避免内存泄漏,每个动态内存分配必须与一个等同相反的deallocation对应。

函数operator delete与delete操作符的关系和operator new与new操作符一样。

注意,在使用placement new在内存建立对象时,应避免使用delete操作符。

应该显式调用对象的析构函数来解除构造函数的影响。

在为对象数组申请空间时必可重载 operator new[] 函数而不再使用operator new函数。

例如

ST *pt = new ST[3];

这个过程共调用3次构造函数

将上例主函数修改为

void main()
{
    ST *pr = new ST[3];
    delete[] pr;//[]一定不可缺少
}

运行结果为

原文地址:https://www.cnblogs.com/area-h-p/p/10345880.html

时间: 2024-10-16 16:00:56

理解各种不同含义的 new 和 delete的相关文章

More Effective C++----(8)理解各种不同含义的new和delete

Item M8:理解各种不同含义的new和delete 人们有时好像喜欢故意使C++语言的术语难以理解.比如说new操作符(new operator)和new操作(operator new)的区别. new操作符和new操作的相关知识请参考<http://blog.csdn.net/qianqin_2014/article/details/51320775> 当你写这样的代码: string *ps = new string("Memory Management"); 你使

深入理解html5标签含义

文章简介: 关于html5相信大家早已经耳熟能详,但是他真正的意义在具体的开发中会有什么作用呢?相对于html,他又有怎样的新的定义与新理念在里面呢?为什么一些专家认为html5完全完成后,所有的工作都可以达到真正的云方式呢?这一系列的问题你是否已经想明白了呢? 本系列文章将为您一一解答你所不知道的关于html5与html中的那些事;具体会包括如:html5新的理念与想法,html5的新标签的用意与具体开发中场景应用,html5与css3的感情经历(用法搭配),包括html5的父亲html的一些

[OpenCV学习]彻底理解卷积的含义

看了很多关于卷积的介绍,一直感觉不怎么理解,今天彻底研究下: 我们知道图像是由像素构成的,图像中的行和列一起构成了图像矩阵,比如一个分辨率800*400的图像,同时也是一个大矩阵,这个矩阵有着400行和800列.假设有一个3*3的滤波小矩阵(卷积核), 在进行卷积运算的时候,我们便利整个图像大矩阵中的每一个像素,先取一个像素,然后取这个像素周围的一圈像素,构成一组3*3的矩阵,与卷积核对应位置的值相乘,把相乘的结果在相加,把相加的结果作为新的值存入结果.概括如下: 卷积就是对图像大矩阵和小矩阵对

理解闭包的含义以及他的使用

1.什么是闭包, 闭包就是能够读取其它函数内部的变量. 首先我们来看一段代码:function a(){ var n = 0; function inc() { n++; console.log(n); } inc(); inc(); } a(); //控制台输出1,再输出2 再来看一段代码: function a(){ var n = 0; this.inc = function () { n++; console.log(n); }; } var c = new a(); c.inc();

【C++常识】more effective C++ 使用条款——基础议题/运算符

第一章:基础议题 Item M1:指针与引用的区别 1.指针可以不初始化,引用必须初始化 2.指针可以为空指针,引用不可以为空 3.指针可以改变指向,引用初始化后就不能改变指向的对象 4.指针占用4个字节,引用只是别名,理论上是不占用空间的,但是这个别名本身是要占用空间的,因此也可以说引用时占用空间的 5.引用比指针效率高,因为引用直接操作的是原对象本身 Item M2:尽量使用C++风格的类型转换 1.C++风格的四种转换:static_cast ,const_cast,dynamic_cas

more effective c++笔记

M1:指针和引用的区别 指针可以指向空值,但引用必须指向一个对象. char *pc=0; char& rc=*pc;//非常有害 不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高,因为在使用引用前不需要测试它的合法性. void printDouble(const double& rd) { cout << rd; // 不需要测试rd,它 } // 肯定指向一个double值 void printDouble(const double *pd) { if

More Effective C++

条款一:指针与引用的区别 指针与引用看上去完全不同(指针用操作符'*'和'->',引用使用操作符'.'),但是它们似乎有相同的功能.指针与引用都是让你间接引用其他对象.你如何决定在什么时候使用指针,在什么时候使用引用呢? 首先,要认识到在任何情况下都不能用指向空值的引用.一个引用必须总是指向某些对象.因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空值给该变量.相反,如果变量肯定指向一个对象,例如你的设计不允许变量为

链表和二叉查找树

<算法>第四版的源代码: http://algs4.cs.princeton.edu/code/ ,看了看还是很有收获! 相同点: 1.链表 :Node包括(value (不一定存什么类型!!!), next , N(可以添加一个参数))  二叉查找树 Node(value(一个键值对,key负责节点的操作,value负责节点存储的信息) , right , left ,N(以该根节点的子节点的节点的个数)) 2.链表(必要元素 head):入口是head,每当我们要操作链表的时候,都要保证新

More Effective C++ (1)

简单分析总结了more effective c++ 的前十个条款: 剩下的条款to be continue~ 1.仔细区分指针和引用引用必须不能指向空,指针可以指向空,指针初始化是记得赋空值,重载某些操作符时(例如[])应该返回引用. 2.最好使用C++转型操作符旧式的C转型应该少用,尽量使用新的C++的转型static_cast<type> (expression)基本上与旧式C转型具有相同的威力与意义.const_cast<type> (expression)用于改变表达式的常