简体   繁体   English

如何实现`new(std :: nothrow)`?

[英]How is `new (std::nothrow)` implemented?

I have a C++ program where the new operator is overloaded. 我有一个C ++程序,其中new运算符被重载。 The problem is that if my allocation in the new operator fails, I'm still calling the constructor. 问题是,如果我在new运算符中的分配失败,我仍然在调用构造函数。 I know I can avoid this by throwing std::bad_alloc , but I don't want to do that. 我知道我可以通过抛出std::bad_alloc来避免这种情况,但我不想这样做。

How can I fail in my overloaded new operator and still not call my constructor? 如何在重载的new运算符中失败并仍然不调用我的构造函数? Essentially I want to implement something like new (std::nothrow) . 基本上我想实现像new (std::nothrow)这样的东西。

Here's an example to illustrate what I mean. 这是一个例子来说明我的意思。 Note that the system I'm testing on has no memory protection. 请注意,我正在测试的系统没有内存保护。 So accessing NULL doesn't do anything 因此访问NULL不会做任何事情

Example 1 : Overloaded new operator 示例1:重载的新运算符

#include <stdio.h>
#include <stdlib.h>
#include <memory>

class Test {

public:

    Test(void) {
        printf("Test constructor\n");
    }

    void print(void) {
        printf("this: %p\n", this);
    }

    void* operator new(size_t size, unsigned int extra) {

        void* ptr = malloc(size + extra);
        ptr = NULL; // For testing purposes
        if (ptr == NULL) {
            // ?
        }
        return ptr;
    }
};

int main(void) {

    Test* t = new (1) Test;            
    t->print();
    printf("t: %p\n", t);

    return 0;
}

The ouput for this is: 这个的输出是:

$ ./a.out
Test constructor
this: 00000000
t: 00000000

Clearly the constrcutor is getting called when the new failed . 显然, new失败时建筑师会被召唤

Example 2 : Huge class declaration with new (std::nothrow) 示例2:使用new(std :: nothrow)的巨大类声明

#include <stdio.h>
#include <stdlib.h>
#include <memory>

class Test {

    int x0[0x0fffffff];
    int x1[0x0fffffff];
    int x2[0x0fffffff];
    int x3[0x0fffffff];
    int x4[0x0fffffff];
    int x5[0x0fffffff];
    int x6[0x0fffffff];
    int x7[0x0fffffff];
    int x8[0x0fffffff];
    int x9[0x0fffffff];
    int xa[0x0fffffff];
    int xb[0x0fffffff];
    int xc[0x0fffffff];
    int xd[0x0fffffff];
    int xe[0x0fffffff];
    int xf[0x0fffffff];

public:

    Test(void) {
        printf("Test constructor\n");
    }

    void print(void) {
        printf("this: %p\n", this);
    }
};

int main(void) {

    Test* t = new (std::nothrow) Test;    
    t->print();
    printf("t: %p\n", t);

    return 0;
}

The ouput for this is: 这个的输出是:

this: 00000000
t: 00000000    

Clearly the constrcutor is not getting called when the new failed . 显然, new失败时建设者不会被召唤

So how do I implement new (std::nothrow) kind of functionality in my overloaded new operator? 那么如何在重载的new运算符中实现new (std::nothrow)类功能呢?

Whether the compiler checks for a null pointer after calling operator new or not, before calling the destructor, depends on whether the allocator function has a non-throwing exception specification or not. 在调用析构函数之前,编译器是否在调用operator new之后检查空指针取决于分配器函数是否具有非抛出异常规范。 If not, the compiler assumes that operator new will throw if no memory is available. 如果没有,编译器假定如果没有可用内存,则将抛出operator new Otherwise, it assumes that operator new will return a null pointer. 否则,它假定operator new将返回空指针。 In your case, your operator new should be: 在您的情况下,您的operator new应该是:

void* operator new( size_t size, unsigned int extra ) throw()
{
    //...
}

or if you can count on C++11 support: 或者,如果你可以指望C ++ 11支持:

void* operator new( size_t size, unsigned int extra) noexcept
{
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM