[关闭]
@nrailgun 2015-09-14T15:05:44.000000Z 字数 1452 阅读 2110

C++:::operator newnew operator

程序设计


C++ 的操作符重载是一个比较复杂的东西,而 new 是其中比较特殊的一个。

new operator

C++ 使用 new operator 动态申请空间:

  1. int main()
  2. {
  3. string *s;
  4. s = new string("!");
  5. delete s;
  6. }

new expression

new 表达式(new expression)具有两种形式。

分配内存,构造对象:

  1. int main()
  2. {
  3. string *s;
  4. s = new string("!");
  5. return 0;
  6. }

不分配内存,只构造对象:

  1. int main()
  2. {
  3. string *s;
  4. s = (string *) malloc(sizeof(string));
  5. new (s) string("!");
  6. return 0;
  7. }

new operator 的行为

虽然 new expression 具有两种不同的行为,然而抽象而言,new 包含了以下操作:

  1. 调用 ::operator new 分配内存;
  2. 类型指针类型转化(Trivial, isn't it?);
  3. 调用构造函数;

什么是 ::operator new 呢?::operator new 是 C++ 标准库对于 new 表达式中分配内存行为的具体实现(注:表达式 2 不分配内存,见下文)。`

重载 ::operator new

::operator new 具有三个 prototype,定义在全局定义域:

  1. // exception throwing (1)
  2. void* operator new (std::size_t size) throw (std::bad_alloc);
  3. // exception nothrow (2)
  4. void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw();
  5. // placement (3)
  6. void* operator new (std::size_t size, void* ptr) throw();

“placement” 取“占位”之意。在 new 过程中,::operator new (1)、(2) 被调用,分配内存;如果只构造而不分配内存,那么 placement (3) 版本将会被调用。Placement (3) 不分配内存,什么也不做,纯粹占位,所以称之为“placement”。

前两个版本可以被 overload 或者 replace,以实现自己的内存分配。一般而言,通过自己分配内存而提高程序效率比较困难,大部分情况下都是用来做内存泄露检测:

  1. void *operator new (std::size_t sz)
  2. {
  3. log(time(), proc_stack(), sz);
  4. return malloc(sz);
  5. }

::operator new 属于动态链接

注意 overload 和 replace 的区别。overload 是指为函数提供不同的形式参数或者模板参数,而 replace 是指覆盖原有定义。有同学质疑为何重复定义 ::operator new 不会导致链接器报错。这是因为默认情况下,链接器链接动态库不会管 multiple definition,而静态库默认对 multiple definition 报错。

= =|||,虽然我觉得这问题没啥意义,链接器爱怎么链接就怎么链接,这不都是 Richard Stallman 说了算么。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注