2

可能重复:
公共运算符 new,私有运算符删除:使用 new 时获取 C2248“无法访问私有成员”

http://efesx.com/2009/12/01/public-operator-new-and-private-operator-delete/

在这篇文章中,我读到这段代码应该给出一个错误:

#include <cstdlib>

struct Try {
        Try () { /* o/ */ }

        void *operator new (size_t size) {
            return malloc(size);
        }

    private:
        void operator delete (void *obj) {
            free(obj);
        }
};

int main () {
    Try *t = new Try();

    return 0;
}

我用 gcc 4.7.1 试过了:

Compilation finished with errors: source.cpp: In function 'int
main()': source.cpp:11:14: error: 'static void Try::operator
delete(void*)' is private source.cpp:17:22: error: within this context
source.cpp:11:14: error: 'static void Try::operator delete(void*)' is
private source.cpp:17:22: error: within this context source.cpp:17:10:
warning: unused variable 't' [-Wunused-variable]

在这篇文章的评论中,我看到了这个链接 - Public operator new, private operator delete: getting C2248 "can not access private member" when using new

如果我理解它是正确的,它不会编译,因为编译器应该通过调用适当的操作符删除在构造函数抛出异常的情况下避免任何内存泄漏。但是为什么这段代码可以编译和工作?

#include <cstdlib>

struct Try {
        void *operator new (size_t size) {
            return malloc(size);
        }

    private:
        void operator delete (void *obj) {
            free(obj);
        }
};

int main () {
    Try *t = new Try;

    return 0;
}

标准是否正确?

那么这段代码呢?

#include <cstdlib>

struct Try {
        void *operator new (size_t size) {
            return malloc(size);
        }

    private:
        void operator delete (void *obj) {
            free(obj);
        }
};

int main () {
    Try *t = new Try();

    return 0;
}

它不能与 gcc 4.7.1 一起编译。

以及如何在标准库中实现这样的事情?

Comeau 并未编译所有这些示例:

"ComeauTest.c", line 15: error: function "Try::operator delete"
(declared at line 9) is inaccessible Try *t = new Try; ^

谁能给我详细解释一下,好吗?

4

2 回答 2

2
  • 看来,您对第一个示例是正确的。

第二个和第三个示例处理 POD 类型。并且有初始化差异起作用。

  • 在第二个示例中,您的结构未初始化。没有问题出现。

  • 相反,在第三个示例结构中确实初始化,所以你得到第一种情况。

编辑:

然后,operator new它本身可以抛出异常。标准(c++11 darft 说):

如果new表达式因抛出异常而终止,它可以通过调用释放函数 (3.7.4.2) 来释放存储空间。如果分配的类型是非数组类型,则分配函数的名称是 operator new,释放函数的名称是operator delete

有点不清楚,作者想表达什么说它可能会释放存储。如果它被释放,它似乎是实现定义的。

无论如何,您可以尝试使用不抛出的new版本:

void *operator new (size_t size, std::nothrow_t) throw() {
    return malloc(size);
}
于 2012-09-21T18:49:49.020 回答
0

如果您的构造函数代码抛出异常,编译器创建的构造函数代码也涉及操作符newdelete 。因此,使用new会自动创建delete的用法。

在第二个示例中,编译器知道您使用从不抛出的默认构造函数(我的猜测)..

不同的编译器以不同的方式工作,因为它们不同(队长)并且具有不同的优化能力和创建代码的技巧

于 2012-09-21T19:55:25.407 回答