• C++中的new用法总结


    前段时间复习面试的时候,看到这个问题经常有问到,我这个小白就看了些博客和书,总结一下。

    new可以说是个一个关键字,也可以说是一个运算符,并且可以被重载。

    1、new operator

    这个就是平时最经常用的new,用法如下程序所示:

     1 class A
     2 {
     3 public:
     4     A(int i) :a(i){}
     5 private:
     6     int a;
     7 };
     8 
     9 int main()
    10 {
    11     A* example = new A(1);
    12 }

    new operator实际上执行了以下三个步骤:

    1、调用operator new分配内存(后面要说的第二种new),如果类本身定义了operator new,那么会调用类自己的operator new,而不是全局的;

    2、调用A的构造函数A::A(int);

    3、返回相应的指针

    2、operator new

    operator new不调用构造函数,而仅仅分配内存,有两个版本,前者抛出异常,后者当失败时不抛出异常,而是直接返回:

    void* operator new (std::size_t size);
    void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) noexcept;

    可以看到,operator new的作用有点类似与C语言中的malloc,有的地方说operator new的底层实现可以是malloc。

    C++中可以用set_new_handler()设置抛出bad_alloc()异常时调用的处理函数,<<Effective C++>>有几个条款很详细描述了具体做法。

    我还是太菜了,水平不够,不太能理解自定义异常处理函数的内容...T T

     1 class A
     2 {
     3 public:
     4     A(int i) :a(i){}
     5     void* operator new(size_t size)
     6     {
     7         cout << "call A::operator new" << endl;
     8         return malloc(size);
     9     }
    10     void operator delete(void* p)
    11     {
    12         cout << "call A::operator delete" << endl;
    13         return free(p);
    14     }
    15     void* operator new(size_t size, const nothrow_t& nothrow_value) noexcept
    16     {
    17         cout << "call A::operator new (noexcept)" << endl;
    18         return malloc(size);
    19     }
    20     void operator delete(void* p, const nothrow_t& nothrow_value) noexcept
    21     {
    22         cout << "call A::operator delete (noexcept)" << endl;
    23         free(p);
    24     }
    25 private:
    26     int a;
    27 };
    28 
    29 int main()
    30 {
    31     A* example1 = new A(1);
    32     delete example1;
    33     A* example2 = new(nothrow) A(2);
    34     delete example2;
    35 }

    用一个小例子可以证明一下,确实调用的是自定义operator new/delete,而不是全局的。

    3、placement new

    placement new仅在一个已经分配好的内存指针上调用构造函数,基本形式如下:

    void* operator new (std::size_t size, void* ptr) noexcept;

    placement new不需要抛出异常,因为它自身不分配内存。

    同时,ptr指针是已经分配好的,可能在栈上也可能在堆上,如下面的例子:

     1 class A
     2 {
     3 public:
     4     A(int i) :a(i){}
     5     int getValue(){ return a; }
     6 private:
     7     int a;
     8 };
     9 
    10 int main()
    11 {
    12     A* p1 = new A(1);           //在堆上分配
    13     A  A2(2);                    //在栈上分配
    14     A* p2 = &A2;        
    15     cout << "placement new前的值: " << p1->getValue() << "  " << p2->getValue() << endl;
    16 
    17     A* p3 = new(p1) A(3);       //在p1的位置上构造
    18     A* p4 = new(p2) A(4);       //在p2的位置上构造
    19     cout << "placement new后的值: " << p1->getValue() << "  " << p2->getValue() << endl;
    20 }

    第一次输出的是1,2;在相应位置构造后,输出值变为3,4。

  • 相关阅读:
    Oracle db 使用转换函数和条件表达式
    Oracle DB 嵌套函数
    Oracle DB NVL、NVL2、NULLIF、COALESCE函数
    OCP-1Z0-051-V9.02-92题
    OCP-1Z0-051-V9.02-90题
    OCP-1Z0-051-V9.02-89题
    OCP-1Z0-051-V9.02-88题
    OCP-1Z0-051-V9.02-87题
    OCP-1Z0-051-V9.02-86题
    OCP-1Z0-051-V9.02-85题
  • 原文地址:https://www.cnblogs.com/lustar/p/10717502.html
Copyright © 2020-2023  润新知