C ++放置新的'构造函数'的多个参数

时间:2012-10-01 03:52:49

标签: c++ macros placement-new

为了做一些自定义内存跟踪(泄漏防护,损坏检测),我不得不使用placement new来创建C ++对象,这很好 - 但是我很难弄清楚如何将参数传递给构造函数,因为它是从宏调用的(所以文件+行可以自动提供)。

功能:

template <typename T>
T*
cpp_new(
    const char *file,
    size_t line
)
{
    T   *n = (T*)tracked_allocate(&memory_context, sizeof(T), file, line);

    if ( n )
    {
        construct(n);
    }
    else
    {
        throw std::bad_alloc();
    }

    return n;
}

这是通过宏调用的:

#define new_object(type)    cpp_new<type>(__FILE__, __LINE__)

放置新的:

template <typename T>
void
construct(
    T *obj
)
{
    obj = new (obj) T;
}

va_list宏将覆盖可变数量的参数的扩展,只是我不想提供构造函数具有的参数数量,删除va_arg(),并且不能使用va_start(),因为它期望格式。

这有点过头了:http://www.drdobbs.com/cpp/calling-constructors-with-placement-new/232901023?pgno=2

有什么方法可以使用new_object中的__VA_ARGS__并将它们传递给构造函数?每个对象只有一个构造函数,但是有许多不同类型的对象采用不同的参数,所以我想尽可能多地删除手动维护。

或者只是有一种更好的方式来做我正在尝试的事情!

1 个答案:

答案 0 :(得分:4)

你不应该处理construct-if-allocation-succeeded。这是new - 表达式的工作。它可以正确地执行,作为类似事务的操作:要么全部成功,要么在传播异常之前执行清理。

所以,卸下这个责任,宏的工作就是做只有宏可以做的事情,即拿起文件名和行。

这些项目可以/应该传递给分配器功能,然后在技术上是“新的位置”,虽然这里不是就地构建:它是新的位置仅仅因为它有额外的,用户定义的参数,如下所示:

bool hopefully( bool const c ) { return c; }

template< class X >
bool throw_( X const& x ) { throw x; }

void* operator new( size_t const size, char const* const filename, int const linenum )
{
    void* const p = tracked_allocate( &memory_context, size, filename, linenum );
    hopefully( p != 0 )
        || throw_( std::bad_alloc() )
    return p;
}

您需要定义相应的放置释放函数,否则当构造函数抛出时new表达式将无法解除分配:

void operator delete( void* const p )
{
    // Your custom deallocation.
}

void operator delete( void* const p, char const*, int )
{
    ::operator delete( p );
}

现在你的宏只需要提供相关的放置参数,如下所示:

#define SOURCE_LINE_INFO __FILE__, __LINE__

然后你可以说,比如,

new (SOURCE_LINE_INFO) MyType( arg1, arg2, arg3 )

对于更可重用的解决方案,请考虑定义struct以保存文件名和行号。然后宏减少到构造该类型的实例,并且可以更普遍地使用。特别是,它可以用于记录呼叫。