我正在尝试编写禁止堆的类型,即在堆分配的内存上不可构造的类型。通过删除new运算符和new放置符,我想我会实现的。但是使用std::make_shared
创建共享指针仍然可以编译。
删除新运算符后,为什么std::make_shared<A>()
不会编译失败?
#include <memory>
class A {
public:
void* operator new(size_t) = delete;
void* operator new(size_t, void*) = delete;
void* operator new [] (size_t) = delete;
};
// Regular new fails
A* a1 = new A();
// Placement new fails
void* pv = std::malloc(sizeof(A));
A* a2 = new (pv) A();
// make_shared works
std::shared_ptr<A> a3 = std::make_shared<A>();
最佳答案
std::make_shared
是根据::new (pv) T(std::forward<Args>(args)...)
指定的。
[util.smartptr.shared.create]
2效果:分配适用于T型对象的内存
并通过放置在该内存中构造一个对象
new-expression ::new (pv) T(std::forward<Args>(args)...)
。的
模板allocate_shared使用的副本来分配内存。如果
抛出异常,该功能无效。
分配的内存通常用于控制块,而不直接用于new T
。然后通过new放置构造该对象,但是新表达式完全有资格使用全局放置operator new
而不是任何特定于类的表达式。
[expr.new]
9如果new表达式以一元::
运算符开头,则
在全局范围内查找分配函数的名称。
否则,如果分配的类型是类类型T或其数组,
在T的范围内查找分配函数的名称。
查找无法找到名称,或者分配的类型不是类
类型,则在全局范围内查找分配函数的名称。
这两种用法将完全绕过您自定义删除的运算符。
关于c++ - 为什么std::make_shared无法使用已删除的运算符new编译类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59795722/