c++ - g++ 4.9.0 允许我们使用带有布局分配的操作符delete[](void*, size_t)

标签 c++ memory-management g++

我正在使用 g++ 4.9.0 和 N3797 工作草案。我编写了以下简单示例:

#include <iostream>
#include <cstdlib>

using namespace std;

struct A
{
    void* operator new[](size_t t, size_t)
    {
        cout << "allocation" << endl;
        return ::operator new[](t);
    }

    void operator delete[](void *p, size_t t)
    {
        cout << "deallocation" << endl;
        :: operator delete[](p);
    }
};

int main()
{
    A *a = new (90) A[5];
    delete [] a;
}

demo

示例必须反射(reflect)第 3.7.4.2/2 节中的以下脚注规则:

The global operator delete[] with exactly two parameters, the second of which has type std::size_t, is a usual deallocation function.37

37) This deallocation function precludes use of an allocation function void operator new(std::size_t, std::size_t) as a placement allocation function

但事实并非如此。这是一个错误还是脚注只是对实现者的建议?

最佳答案

这是非法的,编译器应该发出诊断信息。从 §5.3.4 [expr.new]/p22 开始,添加了强调:

A declaration of a placement deallocation function matches the declaration of a placement allocation function if it has the same number of parameters and, after parameter transformations (8.3.5), all parameter types except the first are identical. If the lookup finds a single matching deallocation function, that function will be called; otherwise, no deallocation function will be called. If the lookup finds the two-parameter form of a usual deallocation function (3.7.4.2) and that function, considered as a placement deallocation function, would have been selected as a match for the allocation function, the program is ill-formed. For a non-placement allocation function, the normal deallocation function lookup is used to find the matching deallocation function (5.3.5) [ Example:

struct S {
     // Placement allocation function:
    static void* operator new(std::size_t, std::size_t);
    // Usual (non-placement) deallocation function:
    static void operator delete(void*, std::size_t);
};
S* p = new (0) S; // ill-formed: non-placement deallocation function matches
                  // placement allocation function

end example ]

铿锵generates您的代码有错误。

但是,请注意,与全局 operator deleteoperator delete[] 不同,双参数 operator deleteoperator delete[ ] 作为类成员不一定是常用的释放函数(§3.7.4.2 [basic.stc.dynamic.deallocation]/p2):

If a class T has a member deallocation function named operator delete with exactly one parameter, then that function is a usual deallocation function. If class T does not declare such an operator delete but does declare a member deallocation function named operator delete with exactly two parameters, the second of which has type std::size_t, then this function is a usual deallocation function. Similarly, if a class T has a member deallocation function named operator delete[] with exactly one parameter, then that function is a usual (non-placement) deallocation function. If class T does not declare such an operator delete[] but does declare a member deallocation function named operator delete[] with exactly two parameters, the second of which has type std::size_t, then this function is a usual deallocation function.

因此,与全局释放函数不同,如果您声明一个成员operator delete[] (void *),则operator delete[] (void *, std::size_t) 不再是通常的释放函数,而是放置释放函数:

struct A
{
    void* operator new[](size_t t, size_t)
    {
        cout << "allocation" << endl;
        return ::operator new[](t);
    }

    void operator delete[](void *p)
    {
        cout << "deallocation - usual" << endl;
        :: operator delete[](p);
    }
    void operator delete[](void *p, size_t t)
    {
        cout << "deallocation - placement" << endl;
        :: operator delete[](p);
    }
};

还有 clang no longer报告此代码错误。

关于c++ - g++ 4.9.0 允许我们使用带有布局分配的操作符delete[](void*, size_t),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24959192/

相关文章:

c++ - 在没有它们的笔记本电脑上创建 Alt 代码

ios - 如何保留 UIView Controller (ARC)

c++ - 针对 libx264 的链接不起作用 (Cygwin)

c++ - 在 .cpp 文件中包含头文件

c - 为什么在执行 memcpy 时检测到堆栈粉碎?

c++ - 在 Linux 上编译 Python 2.7.3 以嵌入到 C++ 应用程序中

c++ - 导致段错误的简单字符串分配?

c++ - 用 nullptr 初始化

c++ - boost::序列化段错误

c - free() 是否将内存归零?