为什么不用模板实现新的?

Giu*_*Pes 2 c++ memory-management c++11

我正在尝试new使用一些额外的信息来追踪内存泄漏.我知道,我可以new全局覆盖一个运算符,但我惊讶地发现我无法检索有关所分配对象类型的任何信息(如果我错了,请纠正我).显然,当您决定覆盖new运算符时,获取类型信息将是有益的.

例如,我已经实现了一个简单的通用版本newdelete使用了可变参数模板.

std::string to_readable_name(const char * str)
{
    int status;
    char *demangled_name = abi::__cxa_demangle(str, NULL, NULL, &status);
    if(status == 0) {
        std::string name(demangled_name);
        std::free(demangled_name);
        return name;
    }
    return "Unknown";
}

template <typename T, typename... Args>
T * generic_new(Args&&... args) throw (std::bad_alloc)
{
    const std::size_t size = sizeof(T);
    std::cout << "Allocating " << size << " bytes for " << to_readable_name(typeid(T).name()) << std::endl;
    return new T(std::forward<Args>(args)...);
};

template<typename T>
void generic_delete(T* ptr)
{
    const std::size_t size = sizeof(T);
    std::cout << "Deleting " << size << " bytes for " << to_readable_name(typeid(T).name()) << std::endl;
    delete ptr;
}

int main()
{
    auto i = generic_new<int>(0);
    std::cout << *i << std::endl;
    generic_delete(i);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么没有new用模板实现?这将允许开发人员获得有关正在分配的对象类型的信息.

谢谢

Jer*_*fin 5

大多数关于为什么设计C++的问题归结为两种可能性.无论是设计和C++的演化提供了一个理由,或者我们只能推测.我相信这属于后一类.

首先,使用(和替换的能力)operator new(全局和每类)早于向该语言添加模板.因此,最初不能使用模板.图书馆的某些部分被转换为以前没有的模板,但主要是这样做的好处非常明显.

其次,使用具有早期模板功能的编译器的模板可能会导致问题,特别是对于较大的程序.问题是函数模板不是函数 - 它是创建函数的一个方法,可以这么说.换句话说,如果它是作为模板实现的,那么每种类型的每个分配器都会导致实例化一个单独的函数.目前的编译器(和链接器)在合并后很好,但早期的编译器大多数都没有.在大型系统中,您可以轻松地创建数十个甚至数百个单独的分配函数.

最后,模板通常仍然只能是一种正常的用户代码之间的中间层次的东西在提供的东西至少大致一致,以目前的图书馆operator newoperator delete这些传言的OS(或硬件,或其他)弄清楚什么用于从中抽取内存的池,并且(通常)将片段分配给用户代码.在某个地方,您需要一段(通常相当大的)代码来创建和管理内存池.如果这是直接在模板中处理的话,它(实际上)必须在头文件中实现,这也会导致编译时间在66 MHz奔腾甚至是令人难以置信的快速300 MHz DEC上可能是相当不可接受的.阿尔法机器我们大多数人都只能梦想.