avatar

Catalog
C++ 中的 new 关键字

operator new 函数

operator new 作为一个 global namespace 下的普通函数,有三个重载:

c++
1
2
3
void* operator new (std::size_t size);
void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) noexcept;
void* operator new (std::size_t size, void* ptr) noexcept;

可以直接被这样调用:

c++
1
MyClass * p = (MyClass*) ::operator new (sizeof(MyClass));
  • 第一种叫 throwing allocation,如果分配失败会抛一个 bad_alloc 的异常,分配成功就返回新分配空间的起始地址。
  • 第二种叫 nothrow allocation,如果分配失败不会抛异常而是返回一个 null,分配成功就返回新分配空间的起始地址。
  • 第三种叫 placement,需要 include <new>,不会试图分配空间,而是仅仅返回 ptr(看上去没啥用,但是用在 new-expression 中还是很有用的)

new 表达式

上面是直接调用 operator new 这个函数时它的行为,如果用在 new-expression 中会有所不同:首先会以普通函数的形式调用 operator new,这一步如上所述,如果成功会调用 new-expression 中类的构造函数,构造到刚才 operator new 返回的地址中,最后返回一个相应类型的指针。

  • 第一种是最简单的 new-expression:

    c++
    1
    2
    3
    MyClass * p1 = new MyClass;
    // allocates memory by calling: operator new (sizeof(MyClass))
    // and then constructs an object at the newly allocated space
  • 第二种需要在 new 后面加上 (std::nothrow)

    c++
    1
    2
    3
     MyClass * p2 = new (std::nothrow) MyClass;
    // allocates memory by calling: operator new (sizeof(MyClass), std::nothrow)
    // and then constructs an object at the newly allocated space
  • 第三种需要在 new 后面加上一个地址:

    c++
    1
    2
    3
    new (p2) MyClass;
    // does not allocate memory -- calls: operator new (sizeof(MyClass), p2)
    // but constructs an object at p2

总结

总结一下就是仅仅调用 ::operator new 是分配空间(第三种除外),而 new-expression 则是分配空间加构造对象,前两种是在分配的新空间上构造,第三种是在指定的地址构造。

Reference

Author: Gusabary
Link: http://gusabary.cn/2020/02/26/C++%E4%B8%AD%E7%9A%84new%E5%85%B3%E9%94%AE%E5%AD%97/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

Comment