new和delete

new和delete的用法,参考[1]

  • new() 分配这种类型的一个大小的内存空间,并以括号中的值来初始化这个变量; 
  • new[] 分配这种类型的n个大小的内存空间,并用默认构造函数来初始化这些变量;

使用举例:

1、new和new[]

#include <iostream>
#include <string.h>
using namespace std;

int main(){
    
    //char * p=new char("Hello");
    //error,分配一个char(1字节)的空间,
    //用"Hello"来初始化,这明显不对

    char* p=new char[6];
    //p="Hello";
    //不能将字符串直接赋值给该字符指针p,原因是:
    //指针p指向的是字符串的第一个字符,只能用下面的
    //strcpy

    strcpy(p,"Hello");
    cout<<*p<<endl; //只是输出p指向的字符串的第一个字符!
    cout<<p<<endl; //输出p指向的字符串!
    delete[] p;

return 0;
}

输出结果:

H
Hello

 

2、new的同时初始化:

int *a = new int ;   //将一个int类型的地址赋值给整型指针a.
int *a = new int(5);//作用同上,但是同时将指针指向的内容赋值为5

 

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

int *p1 = new int[10];
//返回的是一个指向int的指针int*,开辟一个大小为10的整形数组空间;

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].

 

4、delete

int *a = new int;
delete a; //释放单个int的空间

int *a = new int[5];
delete [] a; //释放int数组空间

int (*p2)[10] = new int[2][10];
delete [] p2; //不管数组是几维的,delete的形式都是一样的;

 

5、new运算符

最常用的是作为运算符的new,比如:

string *str = new string(“test new”);

作为运算符,new和sizeof一样,是C 内置的,你不能对它做任何的改变,除了使用它。
new会在堆上分配一块内存,并会自动调用类的构造函数

 

6、切记切记,new/delete、new[]/delete[] 要配套使用。至于原因,参见[2][3]。delete掉一块内存,具体的是执行了什么操作呢?

       如果说这块内存总是保存的普通的变量,此时编译器只会释放此指针所指向的内存空间,而不会破坏这个指针本身,指针本身的值还是原来的值,而指针指向的内容可能变为随机数,例如-572662307(vs中),也可能保持不变(gcc中)

      如果说这块内存中本身还存在指针,那么delete后这块内存中的指针本身的值可能变为随机数,比如:-572662307(意味着此时该指针的指向发生了变化),可能保持不变(gcc中)。而指向这块内存的指针本身不会变,这是确定的。总之很神奇,是和编译器相关的。

 

     不管在哪个编译器中,delete掉一块内存之后,记得把指向这块内存的指针赋值为NULL,否则的话会很危险,详见delete *p之后一定要加上: p=NULL。比如说程序在之后的代码中又new了内存,此时分配的内存很可能就是刚刚delete掉的内存,那么之前指向这块内存的指针就拥有修改这块内存中数据的能力,而这是我们不希望的,所以当delete的时候,一定记得顺手把此时的指针指向NULL。

 

7、别人new和delete;

int*** a= new int**[5];
for (int i = 0; i < 5; ++i)
{
     a[i] = new int*[6];
     for (int j = 0; j < 6; ++j)
    {
            a[i][j] = new int[7];
     }
}
for (int i = 0; i < 5; ++i)
{
     for (int j = 0; j < 6; ++j)
     {
           delete[] a[i][j];
     }
     delete[] a[i];
}
delete[] a;

参考:new创建 一维数组、二维数组、三维数组

参考:

[1] new与delete的基础用法

[2]  浅谈 C++ 中的 new/delete 和 new[]/delete[]背后的机制

operator new 和 operator delete 其实是 C++ 语言标准库的库函数,原型分别如下:

void *operator new(size_t);     //allocate an object
void *operator delete(void *);    //free an object

void *operator new[](size_t);     //allocate an array
void *operator delete[](void *);    //free an array

C++ Primer 一书上说这不是重载 new 和 delete 表达式(如 operator= 就是重载 = 操作符),因为 new 和 delete 是不允许重载的。

[3] C++中delete和delete[]的区别

 基本类型的对象没有析构函数,所以回收基本类型组成的数组空间用 delete 和 delete[] 都是应该可以的;但是对于类对象数组,只能用 delete[]。对于 new 的单个对象,只能用 delete 不能用 delete[] 回收空间。

[4] 关于库函数free p是怎样知道要删除的内存空间大小

其实真正的内存管理如申请/释放等,并不是由malloc或者free等库函数来负责的,而是交由操作系统去完成,它们只是维护一个空闲的链表式的内存块,理解这一点是问题的关键。例如:要申请sizeof(int)*100大小的内存空间,虽然返回的是内存大小是400,但实际上,操作系统分配时候,会多出一块用于存储内存大小的类似链表head头节点的东东,这个节点存储的是空间的首地址及分配内存的大小。

[5] new和delete的底层实现

new -> operator new -> malloc -> 构造函数

new []-> operator new [] -> operator new -> malloc -> 构造函数

delete -> 析构函数 -> operator delete -> free

delete [] -> 析构函数 -> operator delete [] -> operator delete -> free

 

附加:

说一个有趣的事情,和本文关系不大哈。我用的code::blocks,在使用scanf,getc等需要标准输入的时候,从键盘输入数据的时候,如果这时候的输入法是中文的话,按字母和数字是不显示东西的,然后一按enter哗啦一下把刚才你按的东西给你显示在屏幕上,卧槽,我一开始还以为是我写的代码有问题,按enter输出缓冲区的数据了呢,还上网各种查找缓冲区刷新的知识。后来一看原来是输入法没切换,尴尬,真是。。。。所以说,码代码把输入法切换到英文输入!

       之前我用C-Free的时候,这种情况就不会有问题,即使中文输入,其还和在word上面打字一样,有输入法的中文候选词的出现,这时你就能意识到输入法该切换了。

       上面说到的问题,我发现不是IDE的问题,是操作系统的问题,之前用C-Free是在win7上,而我是用Code::blocks是在win10上,所以才有了上面的区别。

 

       但是code::blocks和C-Free确实有不同的地方,code::blocks 在程序结束之后,自动的给补一个回车,这样的话,“请按任意键继续”这句话就不会和程序的输出在同一行上面。但是C-Free就不一样,它不添加回车,如果程序最后的输入不加'n'的话,那么“请按任意键继续”这句话就会出现在程序输出的同一行上面,但是这个做法是和gcc编译器一致的。

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值