重载new和delete的nothrow版本

sri*_*anp 3 c++

请看下面的代码:

#include<iostream>
#include<stdlib.h>
#include<new>

using namespace std;


class ex
{
     int x;
public:
     ex():ex(0){}
     ex(int x):x(x)
     {
     //cout<<"\nConstructor";
     }


 void *operator new(size_t siz)
 {
     void *p;
     cout<<"\nOverloaded new operator normal version";
     p=malloc(siz);
     if(p==NULL)
     {
         bad_alloc ba;
         throw ba;
     }
     else
        return p;
 }
 void operator delete(void *p,size_t sz)
 {
     cout<<"\nOverloaded delete normal version:"<<sz;
     free(p);
 }


 void *operator new(size_t siz,const nothrow_t &tag)
 {
     void *p;
     cout<<"\nOverloaded new operator nothrow version";
     p=malloc(siz);
     if(p==NULL)
     {
        return 0;
     }
     else
        return p;
 }
 void operator delete(void *p,const nothrow_t &tag)
 {
     cout<<"\nOverloaded delete nothrow version";
     free(p);
 }


 void *operator new[](size_t siz)
 {
     void *p;
     cout<<"\nOverloaded new operator normal version in array";
     p=malloc(siz);
     if(p==NULL)
     {
         bad_alloc ba;
         throw ba;
     }
     else
        return p;
 }
 void operator delete[](void *p,size_t sz)
 {
     cout<<"\nOverloaded delete normal version in array:"<<sz;
     free(p);
 }


 void *operator new[](size_t siz,const nothrow_t &tag)
 {
     void *p;
     cout<<"\nOverloaded new operator nothrow version in array";
     p=malloc(siz);
     if(p==NULL)
     {
         return 0;
     }
     else
        return p;
 }
 void operator delete[](void *p,const nothrow_t &tag)
 {
     cout<<"\nOverloaded delete nothrow version in array";
     free(p);
 }

};


int main()
{
ex *pt;

pt=new ex;
delete pt;

pt=new ex[10];
delete[] pt;

pt=new(nothrow) ex;
delete pt;

pt=new(nothrow) ex[10];
delete[] pt;
}
Run Code Online (Sandbox Code Playgroud)

上述代码的输出:

  Overloaded new operator normal version
  Overloaded delete normal version:4
  Overloaded new operator normal version in array
  Overloaded delete normal version in array:44
  Overloaded new operator nothrow version
  Overloaded delete normal version:4
  Overloaded new operator nothrow version in array
  Overloaded delete normal version in array:44
  Process returned 0 (0x0)   execution time : 0.724 s
  Press any key to continue.
Run Code Online (Sandbox Code Playgroud)

我的问题是:

1)为什么不调用delete的nothrow版本。

2)我可以在删除的无抛出版本中使用大小参数吗?喜欢

  void operator delete[](void *p,const nothrow_t &tag,size_t sz);

  or

  void operator delete(void *p,const nothrow_t &tag,size_t sz);
Run Code Online (Sandbox Code Playgroud)

3)nothrow版本的delete有什么用。

4)我在 new 和 new[] 版本、delete 和 delete[] 版本中使用了相同的代码,但一个是普通变量,另一个是数组变量,这是怎么回事?

5)编译器给出警告:'operator new'不能返回NULL,除非它被声明为'throw()'(或者-fcheck-new有效)如何克服这个问题?

Ami*_*rsh 5

默认行为new

C++bad_alloc失败时会抛出异常,new除非您显式调用new(std::nothrow).

这不受用户是否重载operator new问题的影响。

因此,当您调用new而不传递时std::nothrow,您将不会达到 nothrot 版本。即使你超载了。


new(nothrow)

请注意,您的nothrow版本确实会抛出异常,这不是正确的方法。它应该看起来像:

void* operator new(size_t size, const nothrow_t& tag) noexcept
{
     void* p = malloc(size);
     return p; // don't throw from the nothrow version of new
}
Run Code Online (Sandbox Code Playgroud)

然而,这不会改变所解释的行为:要达到您必须显式调用nothrow它的版本new,正如您在代码中确实看到的那样。


禁用异常

有些编译器允许“禁用”异常,例如--exceptionsgcc 中的标志。这取决于编译器,但在大多数情况下,即使不是全部 - 抛开旧版本的 MSVC - 禁用异常不会导致异常不被抛出,而只会使编译器假设它们不会被抛出,并且调用仍然会new抛出如果失败了。

请参阅:如果我在项目中禁用 C++ 异常,到底会发生什么?

海湾合作委员会示例:http ://coliru.stacked-crooked.com/a/daa465731e56c681


相关SO问题:

也可以很好地阅读:


运算符删除

操作delete员永远不应该抛出异常。它的两个版本,普通版nothrow和普通版(非无抛出)。

nothrow那么版本有什么用呢operator delete

如果new调用分配对象,内存已成功分配,但该对象的构造函数抛出异常,则 new 操作将失败,并传播构造函数抛出的异常。但在此之前需要释放获得的内存。这是通过呼叫delete操作员自动完成的。如果new刚刚失败的是那个nothrow版本,那么delete要调用的操作员就是那个nothrow版本,否则就是正常的操作员。请注意,两个版本的delete运算符都不会也不应该抛出异常。另请注意,您不能自行调用运营商nothrow的版本!delete但您可以创建一个调用它的场景。

例子:

struct A {
    A() {
        throw "bahh";
    }
};

void operator delete(void* ptr) noexcept {
    std::cout << "normal delete" << std::endl;
    free(ptr);
}

void operator delete(void* ptr, const std::nothrow_t&) noexcept {
    std::cout << "nothrow delete" << std::endl;
    free(ptr);
}

int main() {
    std::cout << "calling new A" << std::endl;    
    try {
        new A(); // prints: normal delete
    }
    catch(const char* s) {
        std::cout << s << std::endl; // bahh
    }

    std::cout << "calling new(std::nothrow) A" << std::endl;    
    try {
        new(std::nothrow) A(); // prints: nothrow delete
    }
    catch(const char* s) {
        std::cout << s << std::endl; // bahh
    }
}
Run Code Online (Sandbox Code Playgroud)

代码:http ://coliru.stacked-crooked.com/a/7be9ce12d251b033

看: