c++ - 通过 make_shared 停止堆分配

标签 c++ c++11

我想强制我的对象在堆栈上以执行非常严格的语义并解决一些生命周期问题。我已经阅读了几篇关于如何执行此操作的文章,并最终将 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/

相关文章:

c++ - pybind11 用于 C++14/C++17

c++ - 免费CArchive实现?

c++ - 从 void 函数的 return 语句调用函数

c++ - 如何在最大化大小效率的同时将三态位运算符按位实现到任意大小的内存?

c++ - 用另一个数组初始化指向数组的指针的点

c++ - 正则表达式误解或只是破坏了实现?

c++ - MongoDB C++ 驱动程序 3.0 以字符串形式获取文档并避免使用 json

c++ - max_digits10 的用途是什么?它与 digits10 有何不同?

c++ - 在 C++ 头文件中声明和定义静态变量?

C++ - 从移动赋值运算符调用复制赋值