c++ - C++ 放置的多个参数 new 'constructor'

标签 c++ macros 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

有什么办法可以使用 __VA_ARGS__从 new_object 并将它们传递到构造函数中?每个对象只有一个构造函数,但有许多不同类型的对象采用不同的参数,因此我希望尽可能地消除手动维护。

或者是否有更好的方法来完成我正在尝试的事情!

最佳答案

您不应该处理“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来保存文件名和行号。然后宏简化为构造该类型的实例,并且可以更普遍地使用。特别是,它可以用于记录调用。

关于c++ - C++ 放置的多个参数 new 'constructor',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12667333/

相关文章:

javascript - 网站上自动/预定 JavaScript

c++ - 使用 const 成员放置 new 和类的赋值

c++ - 为什么不能正确解析显式析构函数调用中的限定类型名称?

c++ - std::experimental::optional<T> 实现:Constexpr 构造函数混淆

c# - 此 C 函数的正确 C# PInvoke 签名

c++ - 删除 C++ vector 中的重复条目

python - 如何将 compile_commands.json 与 clang python 绑定(bind)一起使用?

c++ - std::string 在将其用作 (boost.)async_read_some 中的存储时搞砸了

C预处理器: How to create a character literal?

c++ - 宏 'BOOST_FUSION_ADAPT_STRUCT_FILLER_0' 的实际参数过多