c++ - 如何在函数调用后初始化变量,就像 new 表达式提供的那样?

标签 c++ visual-c++ c++14 c++17

目前我正在研究自定义内存分配,其中一个缺点是我必须编写多行代码才能获得与 new-expression 相同的结果。仅提供一个简单的调用。

简单的初始化:

MyClass *obj = new MyClass(3.14);

不太简单的初始化:

void *obj_mem = alloc->Allocate(sizeof MyClass, alignof(MyClass));
MyClass *obj = new(obj_mem) MyClass(3.14);

我将向我的项目组提供分配器,例如那个分配器,并希望他们实际使用它们,而不是返回调用 new,因为我们需要这些更快的分配器来管理我们的内存。

但要实现这一点,我将不得不设计出最简单的语法来使用我的自定义分配器初始化变量。


我的解决方案

我最好的选择是在每个类中覆盖 operator new,因为它是 allocation function对于新表达式。

class MyClass
{
    ...

    void* operator new(size_t size, Allocator *alloc)
    {
        return alloc->Allocate(size, alignof(MyClass));
    }
}

然后初始化变量的语法变成了我最终想要的:

MyClass *obj = new(alloc) MyClass(3.14);

但是,如果我能有一个与上述等价的一般等价物,那就太好了。所以我不必为每个类覆盖 operator new

最佳答案

杀死new完全。无论如何,你必须将创造与破坏捆绑在一起。

template<class T>
struct destroy {
  Alloc* pool = nullptr;
  void operator()(T* t)const { 
    ASSERT(t);
    t->~T();
    ASSERT(alloc);
    alloc->Dealloc( t );
  }
};
template<class T>
using my_unique_ptr = std::unique_ptr<T, destroy<T>>;

namespace details{
  template<class T, class...Args>
  my_unique_ptr<T> my_make_unique( Alloc* alloc, Args&&...args ) {
    void* p_data = alloc->Allocate(sizeof(T), alignof(T));
    try {
      T* ret = ::new(p_data) T(std::forward<Args>(args)...);
      return {ret, destroy<T>{alloc}};
    } catch (...) {
      alloc->Dealloc( p_data );
      throw;
    }
  }
}
/// usual one:
template<class T, class...Args>
my_unique_ptr<T> my_make_unique( Alloc* alloc, Args&&...args ) {
  return details::my_make_unique<T>( alloc, std::forward<Args>(args)... );
}
// permit leading il:
template<class T, class U, class...Args>
my_unique_ptr<T> my_make_unique( Alloc* alloc, std::initializer_list<U> il, Args&&...args ) {
  return details::my_make_unique<T>( alloc, il, std::forward<Args>(args)... );
}
// for {} based construction:
template<class T>struct tag_t{using type=T;};
template<class T>using no_deduction=typename tag_t<T>::type;
template<class T>
my_unique_ptr<T> my_make_unique( Alloc* alloc, no_deduction<T>&&t ) {
  return details::my_make_unique<T>( alloc, std::move(t) );
}

现在my_make_unique需要 Alloc*和构造参数,它返回一个绑定(bind)了销毁代码的智能指针。

这个唯一指针可以传递给一个std::shared_ptr<T>隐式地(通过移动)。

关于c++ - 如何在函数调用后初始化变量,就像 new 表达式提供的那样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40955613/

相关文章:

c++ - msvc 相当于 gcc 的 __BASE_FILE__

为 JNI 编译 64 位 DLL

c++ - 安装 Folly(c++ 库)通过 vcpkg 出错

C++ lambda表达式含义

c++ - 如何创建可变参数泛型 lambda?

c++ - 假设规则和移除分配

c++ - 在单独的可执行文件中调用INSTANTIATE_TEST_CASE_P时,库中的TEST_P测试无法运行

c++ - C++中访问者模式的层次结构实现

c++ - 在 MacOS/Linux 上替换 MS _vscprintf?

C++ 守护进程静默模式