• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > operator new在C++中的各种写法总结

operator new在C++中的各种写法总结

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了operator new,c operator new,operator new函数,c++ operator,c++中的operator等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

乍一看,在C++中动态分配内存很简单:new是分配,delete是释放,就这么简单。然而,这篇文章讲得要复杂一点,并且要考虑到自定义层次。这也许对简单的程序并不重要,但对你在代码中控制内存却是十分必要的,是否能写一个自定义的分配器,某种高级内存管理表或一个特定的垃圾回收机制。

这篇文章并不是一个综合的手册,而是一个C++中各种内存分配方法的概述。它面向已经很熟悉C++语言的读者。

原生operator new

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

int* v = static_cast<int*>(::operator new(5 * sizeof(*v)));

当像如上的调用,operator new扮演原生的内存分配角色,类似malloc。上面等价于:

int* v = static_cast<int*>(malloc(5 * sizeof(*v)));

释放用operator new分配的内存用operator delete:

::operator delete(v);

你愿意永远用原生new和delete函数吗?是,只在极少数不用,我在下面的文章中会论证的。为什么用它们而不用原来的可信的malloc和free呢?一个很充分的原因就是你想保持代码在C++领域的完整性。混合使用new和free(或malloc和delete)是很不可取的(big NO NO)。用new和delete的另一个原因是你可以重载(overload)或重写(override)这些函数,只要你需要。下面是个例子:

void operator delete(void* ptr) throw()
{
    cerr << "deallocating at " << ptr << endl;
    free(ptr);
}
</div>
通常,注意到new被用来给内置类型,不包含用户自定义new函数的类的对象,和任意类型的数组分配空间,使用的都是全局的运算符new。当new被用来为已经被重定义new的类实例化时,用的就是那个类的new函数。

下面来看下带new函数的类。

特定类的operator new
大家有时很好奇"operator new"和"new operator"的区别。前者可以是一个重载的operator new,全局的或者特定类或者原生的operator new。后者是你经常用来分配内存的C++内置的new operator,就像:

Car* mycar = new Car;

C++支持操作符重载,并且我们可以重载的其中一个就是new。

下面是个例子:

    void operator delete(void* p)
    {
        cerr << "deleten";
        ::operator delete(p);
    }
private:
    int m_data;
};

class Derived : public Base
{
private:
    int m_derived_data;
    vector<int> z, y, x, w;
};

int main()
{
    Base* b = new Base;
    delete b;

    Derived* d = new Derived;
    delete d;
    return 0;
}
</div>
打印结果:
new 4 bytes
delete
new 56 bytes
delete

在基类被重载的operator new和operator delete也同样被子类继承。如你所见,operator new得到了两个类的正确大小。注意实际分配内存时使用了::operator new,这是前面所描述过的原生new。在调用前面的两个冒号很关键,是为了避免进行无限递归(没有它函数将一直调用自己下去)。

为什么你要为一个类重载operator new?这里有许多理由。

性能:默认的内存分配算符被设计成通用的。有时你想分配给一个非常特殊的对象,通过自定义分配方式可以明显地提高内存管理。许多书和文章都讨论了这种情况。尤其是"Modern C++ Design"的第4章展示了一个为较小的对象的非常好的设计并实现了自定义的分配算符。

调试 & 统计:完全掌握内存的分配和释放为调试提供了很好的灵活性,统计信息和性能分析。你可将你的分配算符插入进专门用来探测缓冲区溢出的守卫,通过分配算符和释放算符(deallocations)的比较来检测内存泄漏,为统计和性能分析积累各种指标,等等。

个性化:对于非标准的内存分配方式。一个很好的例子是内存池或arenas,它们都使得内存管理变得更简单。另一个例子是某个对象的完善的垃圾回收系统,可以通过为一个类或整个层面写你自己的operators new和delete。

研究在C++中new运算符是很有帮助的。分配是分两步进行:

1.  首先,用全局operator new指导系统请求原生内存。
2.  一旦请求内存被分配,一个新的对象就在其中开始构造。

The C++ FAQ给出一个很好的例子,我很愿意在这里这出来:

当你写下这段代码:

Foo* p = new Foo();

编译器会生成类似这种功能的代码:

 // don't catch exceptions thrown by the allocator itself

//不用捕捉分配器自己抛出的异常

 void* raw = operator new(sizeof(Foo));

 // catch any exceptions thrown by the ctor

//捕捉ctor抛出的任何异常

 try {
   p = new(raw) Foo();  // call the ctor with raw as this 像这样用raw调用ctor分配内存
 }
 catch (...) {
   // oops, ctor threw an exception 啊哦,ctor抛出了异常
   operator delete(raw);
   throw;  // rethrow the ctor's exception 重新抛出ctor的异常
 }
</div>
其中在try中很有趣的一段语法被称为"placement new",我们马上就会讨论到。为了使讨论完整,我们来看下用delete来释放一个对象时一个相似的情况,它也是分两步进行:

1.首先,将要被删除对象的析构函数被调用。
2.然后,被对象占用的内存通过全局operator delete函数返还给系统。

所以:
delete p;
等价于[2]:
if (p != NULL) {
  p->~Foo();
  operator delete(p);
}

这时正适合我重复这篇文章第一段提到的,如果一个类有它自己的operator new或 operator delete,这些函数将被调用,而不是调用全局的函数来分配和收回内存。

Placement new
现在,回来我们上面看到样例代码中的"placement new"问题。它恰好真的能用在C++代码中的语法。首先,我想简单地解释它如何工作。然后,我们将看到它在什么时候有用。

直接调用 placement new会跳过对象分配的第一步。也就是说我们不会向操作系统请求内存。而是告诉它有一块内存用来构造对象[3]。下面的代码表明了这点:
&nb

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • operator new在C++中的各种写法总结
  • 全面解析C++中的new,operator new与placement new

相关文章

  • 2017-05-28VC++实现程序开机启动运行的方法
  • 2017-05-28利用c语言实现卷积码编码器示例
  • 2017-05-28C++如何实现广义表详解
  • 2017-05-28深入详解C编写Windows服务程序的五个步骤
  • 2017-05-28C++编程中私有和保护以及公有的类成员访问控制
  • 2017-05-28C语言 结构体和指针详解及简单示例
  • 2017-05-28关于C/C++中typedef的定义与用法总结
  • 2017-05-28C语言运算符的优先级和结合性实例详解
  • 2017-05-28C语言中正切的相关函数总结
  • 2017-05-28visual studio 2015下boost库配置教程

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • LintCode 堆化详解及实例代码
    • C语言实现xml构造解析器
    • C++编写简单的打靶游戏
    • C语言之实现控制台光标随意移动的实例代码
    • C语言新建临时文件和临时文件名的方法
    • C语言fopen函数的用法,C语言打开文件详解
    • 浅谈C++左值引用和右值引用
    • C语言编译和链接详解(通俗易懂,深入本质)
    • C语言的Struct Hack笔记
    • c++中const的使用详解

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有