C++中new的用法及说明

 更新时间:2022年11月07日 09:43:26   作者:见牛羊  
这篇文章主要介绍了C++中new的用法及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

C++ new的用法

知识点小结

new其实就是告诉计算机开辟一段新的空间,但是和一般的声明不同的是,new开辟的空间在堆上,而一般声明的变量存放在栈上。

通常来说,当在局部函数中new出一段新的空间,该段空间在局部函数调用结束后仍然能够使用,可以用来向主函数传递参数。

另外需要注意的是,new的使用格式,new出来的是一段空间的首地址。所以一般需要用指针来存放这段地址。

具体的代码如下:

#include <iostream>
using namespace std;
 
int example1()
{
  //可以在new后面直接赋值
  int *p = new int(3);
  //也可以单独赋值
  //*p = 3;
 
  //如果不想使用指针,可以定义一个变量,在new之前用“*”表示new出来的内容
  int q = *new int;
  q = 1;
  cout << q << endl;
 
  return *p;
}
 
int* example2()
{
  //当new一个数组时,同样用一个指针接住数组的首地址
  int *q = new int[3];
  for(int i=0; i<3; i++)
    q[i] = i;
 
  return q;
}
 
struct student
{
  string name;
  int score;
};
 
 
student* example3()
{
  //这里是用一个结构体指针接住结构体数组的首地址
  //对于结构体指针,个人认为目前这种赋值方法比较方便
  student *stlist = new student[3]{{"abc", 90}, {"bac", 78}, {"ccd", 93}};
 
  return stlist;
}
 
 
 
int main()
{
  int e1 = example1();
  cout <<"e1: "<< e1 << endl;
 
  int *e2 = example2();
  for(int i=0; i<3; i++)
    cout << e2[i] << " ";
  cout << endl;
 
 
  student *st1 = example3();
 
  for(int i=0; i<3; i++)
    cout << st1[i].name << " " << st1[i].score << endl;
 
 
 
  return 0;
}

new的三种使用方法

概念

在C++中new的三种用法包括:plain new, nothrow new 和 placement new。

plain new 就是我们最常使用的new的方式,在C++中的定义如下:

1 void* operator new(std::size_t) throw(std::bad_alloc);  
2 void operator delete( void *) throw();

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

nothrow new 是不抛出异常的运算符new的形式。nothrow new在失败时,返回NULL。定义如下:

1 void * operator new(std::size_t, const std::nothrow_t&) throw();
2 void operator delete(void*) throw();

placement new 意即“放置”,这种new允许在一块已经分配成功的内存上重新构造对象或对象数组。placement new不用担心内存分配失败,因为它根本不分配内存,它做的唯一一件事情就是调用对象的构造函数。定义如下:

1 void* operator new(size_t, void*);
2 void operator delete(void*, void*);

palcement new 的主要用途就是反复使用一块较大的动态分配的内存来构造不同类型的对象或者他们的数组。placement new构造起来的对象或其数组,要显示的调用他们的析构函数来销毁,千万不要使用delete。

示例

  • plain new
char *getMemory(unsigned long size)   
{    
    char * p = new char[size];   
    return p; 
}   
void main(void)   
{
    try{   
        char * p = getMemory(1000000);    // 可能发生异常
        // ...   
        delete [] p;   
    }   
    catch(const std::bad_alloc &amp; ex)   
    {
        cout &lt;&lt; ex.what();
    }   
}
  • nowthrow new
void func(unsinged long length)   
{
    unsinged char * p = new(nothrow) unsinged char[length];   
    // 在使用这种new时要加(nothrow) ,明示不使用异常处理 。
 
    if (p == NULL)  // 因不抛异常,故定要检查
        cout << "allocte failed !";   
        // ...   
    delete [] p;
}
  • placement new
void main()   
{  
    using namespace std;   
    char * p = new(nothrow) char [4];   
    if (p == NULL)   
    {
        cout << "allocte failed" << endl;  
        exit( -1 );
    }   
    // ...   
    long * q = new (p) long(1000);   
    delete []p;    // 只释放 p,不要用q释放。
}

p和q仅仅是首址相同,所构建的对象可以类型不同。所“放置”的空间应小于原空间,以防不测。当”放置new”超过了申请的范围,Debug版下会挂机,但Release版竟然能运行而不出错!

该运算符的作用是:只要第一次分配成功,不再担心分配失败。

void main()   
{
    using namespace std;   
    char * p = new(nothrow) char [100];   
    if (p == NULL)   
    {  
        cout << "allocte failed" << endl;
        exit(-1);
    }   
    long * q1 = new (p) long(100);   
    // 使用q1  ...   
    int * q2 = new (p) int[100/sizeof(int)];   
    // 使用q2 ...   
    ADT * q3 = new (p) ADT[100/sizeof(ADT)];   
    // 使用q3  然后释放对象 ...   
    delete [] p;    // 只释放空间,不再析构对象。
}

注意:使用该运算符构造的对象或数组,一定要显式调用析构函数,不可用delete代替析构,因为placement new 的对象的大小不再与原空间相同。

void main()   
{  
    using namespace std;   
    char * p = new(nothrow) char [sizeof(ADT)+2];   
    if (p == NULL)   
    {  
        cout << "allocte failed" &lt;&lt; endl;
        exit(-1); 
    } 
    // ... 
    ADT * q = new (p) ADT; 
    // ... 
    // delete q; // 错误
    q->ADT::~ADT();  // 显式调用析构函数,仅释放对象
    delete [] p;     // 最后,再用原指针来释放内存
}

placement new 的主要用途就是可以反复使用一块已申请成功的内存空间。这样可以避免申请失败的徒劳,又可以避免使用后的释放。

特别要注意的是对于 placement new 绝不可以调用的delete, 因为该new只是使用别人替它申请的地方(只是个租房户,不是房主。无权将房子卖掉)。释放内存是nothrow new的事,即要使用原来的指针释放内存。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • C++控制权限关键字protected

    C++控制权限关键字protected

    这篇文章主要介绍了C++控制权限关键字protected,protected和private类似,而对于派生类来说,protected与public类似,下面来一起俩姐更多详细内容吧,需要的小伙伴可以参考一下
    2022-01-01
  • c++访问私有private成员变量的常用方法

    c++访问私有private成员变量的常用方法

    这篇文章主要介绍了c++访问私有private成员变量的常用方法,需要的朋友可以参考下
    2020-08-08
  • C++实现稀疏矩阵的压缩存储实例

    C++实现稀疏矩阵的压缩存储实例

    本篇文章主要介绍了C++实现稀疏矩阵的压缩存储实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • 分享一下8年C++面向对象设计的经验体会

    分享一下8年C++面向对象设计的经验体会

    关于C++程序设计的书藉非常多,本章不讲C++的语法,只讲一些小小的编程道理。如果我能早几年明白这些小道理,就可以大大改善数十万行程序的质量了
    2017-07-07
  • C语言数据结构之线性表的链式存储结构

    C语言数据结构之线性表的链式存储结构

    线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列,这篇文章带你学习下线性表的链式存储结构
    2021-11-11
  • C语言头文件<string.h>函数详解

    C语言头文件<string.h>函数详解

    本文主要介绍了C语言头文件<string.h>函数详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 深度理解c++中的this指针

    深度理解c++中的this指针

    这篇文章主要介绍了C++编程指向成员的指针以及this指针的基本使用指南,与C语言一样,存储的数值被解释成为内存里的一个地址,需要的朋友可以参考下。
    2016-07-07
  • 用C语言实现简单的计算器功能

    用C语言实现简单的计算器功能

    这篇文章主要为大家详细介绍了用C语言实现简单的计算器功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • C++中set/multiset容器详解(附测试用例与结果图)

    C++中set/multiset容器详解(附测试用例与结果图)

    set/multiset属于关联式容器,底层结构是用二叉树实现,下面这篇文章主要给大家介绍了关于C++中set/multiset容器的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • QT使用Http协议通信的实现示例

    QT使用Http协议通信的实现示例

    使用QT进行应用开发时,有时候需要进行客户端和服务端的网络通信,本文主要介绍了QT使用Http协议通信的实现示例,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12

最新评论