读《Effective C++》(一)

关于operator new的一些理解,算是重读《Effective C++》有感

1. operator new的实现

# in gcc/libstdc++-v3/libsupc++/new_op.cc
....
#include <bits/c++config.h>
#include <cstdlib>
#include <bits/exception_defines.h>
#include "new"

using std::new_handler;
using std::bad_alloc;
#if _GLIBCXX_HOSTED
using std::malloc;
#else
// A freestanding C runtime may not provide "malloc" -- but there is no
// other reasonable way to implement "operator new".
extern "C" void *malloc (std::size_t);
#endif

_GLIBCXX_WEAK_DEFINITION void *
operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
{
    void *p;

    /* malloc (0) is unpredictable; avoid it.  */
    if (sz == 0)
        sz = 1;

    while (__builtin_expect ((p = malloc (sz)) == 0, false))
    {
        new_handler handler = std::get_new_handler ();
        if (! handler)
        _GLIBCXX_THROW_OR_ABORT(bad_alloc());
        handler ();
    }

    return p;
}

2. 我们看到并需要理解的

2.1 handler函数是循环调用的

如果malloc没有成功,handler函数会循环调用,除非我们将handler设置为空,或者在handler中抛出异常。这样我们再去看条款49也就比较好理解了。

3. placement new

如果operator new接受的参数除了一定会有的那个size_t之外,还有其他的参数,这便是所谓的placement new。

# in gcc/libstdc++-v3/libsupc++/new
// Default placement versions of operator new.
inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }

说到placement new,最先想到的就是上面这个版本,输入一个内存区域指针。看到实现发现,如此简单,就直接返回了。

3.1 placement new / delete

如果实现了placement new,则需要实现对应的placement delete。因为如果类构造函数出异常了,c++内部会调用对应的placement delete。

4. 关于构造函数和析构函数出问题需要怎么处理

参考:https://isocpp.org/wiki/faq/exceptions#ctors-can-throw

在构造函数中,抛出异常;在析构函数中,中断程序。