通过make_shared停止堆分配

Jar*_*edC 6 c++ c++11

我想强制我的对象在堆栈上强制执行非常严格的语义并解决一些生命周期问题.我已经阅读了几篇关于如何做到这一点的文章,并开始operator new私有化(或删除).这似乎new直接使用时可以正常工作,但make_shared编译得很好.

#include <boost/smart_ptr.hpp>

class A
{
private:
   void *operator new( size_t );
   void operator delete( void* );
   void *operator new[]( size_t );
   void operator delete[]( void* );
};

int main()
{
//  A* a = new A;      // Correctly produces compile error
    boost::shared_ptr<A> a2 = boost::make_shared<A>();
}
Run Code Online (Sandbox Code Playgroud)

使用new A直接给我这个错误按预期:

error: ‘static void* A::operator new(size_t)’ is private
Run Code Online (Sandbox Code Playgroud)

我猜这make_shared是有效的,因为它正在使用placement new运算符,但我找不到任何讨论如何禁止这个的文章.我提出的最佳解决方案是明确删除模板专门化make_shared

namespace boost
{
    template<>
    shared_ptr<A> make_shared<A>() = delete;
};
Run Code Online (Sandbox Code Playgroud)

这显然是非常具体的boost::make_shared.这真的是最好的方式吗?

Ben*_*igt 4

的放置形式new非常容易处理——它们只是带有额外的参数。例如,简单的放置形式是

void* operator new(std::size_t, void*);
Run Code Online (Sandbox Code Playgroud)

请注意,18.6.1.3 禁止在全局范围内重新定义这些;但是,为您的特定类型重新定义(或删除/使其不可访问)它们应该没有问题。

不幸的是,make_shared使用作用域::new (pv) T(std::forward<Args>(args)...)。正如我所提到的,你不能扰乱新的全球布局。因此,您无法在编译时阻止它,任何运行时陷阱都将是一种黑客攻击(检查指针this以查看它是否在堆栈范围内)。