我想强制我的对象在堆栈上以执行非常严格的语义并解决一些生命周期问题。我已经阅读了几篇关于如何执行此操作的文章,并最终将 operator new
设为私有(private)(或删除)。当直接使用 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>();
}
直接使用 new A
会出现预期的错误:
error: ‘static void* A::operator new(size_t)’ is private
我猜测 make_shared
正在工作,因为它使用了放置新运算符,但我找不到任何讨论如何禁止它的文章。我想到的最佳解决方案是显式删除 make_shared
namespace boost
{
template<>
shared_ptr<A> make_shared<A>() = delete;
};
虽然这显然是非常特定于 boost::make_shared
的。这真的是最好的方法吗?
最佳答案
new
的放置形式很容易处理——它们只是带有额外的参数。比如简单的放置形式是
void* operator new(std::size_t, void*);
请注意,18.6.1.3 禁止在全局范围内重新定义这些;但是,为您的特定类型重新定义(或删除/使其不可访问)应该没有问题。
不幸的是,make_shared
使用范围 ::new (pv) T(std::forward<Args>(args)...)
.正如我所提到的,您不能乱用新的全局布局。所以你不能在编译时阻止它,任何运行时陷阱都是黑客攻击(检查 this
指针以查看它是否在堆栈的边界内)。
关于c++ - 通过 make_shared 停止堆分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14027079/