使用时std::make_shared<C>
不会调用类重载的 new/delete 运算符。
使用时std::shared_ptr<C>
, std::unique_ptr<C>
& std::make_unique<C>
使用类重载的 new/delete 运算符。
当查看文档时,它是完全正确且有据可查的。
参考参数 https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared解释该行为:
std::make_shared
使用 ::new,因此如果使用特定于类的运算符 new 设置了任何特殊行为,它将不同于std::shared_ptr<T>(new T(args...))
.
下面是一些伪代码,可以更好地突出显示该行为:
#include <memory>
class C {
public:
void* operator new(size_t size) {
void* p = ::operator new(size);
std::cout << "C::new() -> " << p << "\n";
return p;
}
void operator delete(void* p) {
std::cout << "C::delete() -> " << p << "\n";
::operator delete(p);
}
};
std::shared_ptr<C> ptr = std::make_shared<C>();
从外部的角度来看,它似乎不一致并且容易出错。应始终使用重载类 new/delete 运算符。
那么,这种行为的理由是什么?
并且,详细说明的 C++ 规范在哪里?std::make_shared
行为?
感谢您的帮助。
那么,这种行为的合理性是什么呢?
这样做的原因是因为make_shared
不只是分配你的对象,它还分配控制块shared_ptr
。为了使其尽可能高效,它调用new
一次并为控制块和对象一次性分配足够的存储空间。否则就必须调用new
两倍,使分配开销加倍。
如果您想使用自定义分配器,那么您需要使用std::allocate_shared https://en.cppreference.com/w/cpp/memory/shared_ptr/allocate_shared它将使用您的自定义分配器进行一次内存获取来创建shared_ptr
.
另一种选择是使用std::make_unique
创建一个unique_ptr
,然后用它来初始化shared_ptr
。这有效是因为unique_ptr
没有控制块所以std::make_unique
分配形式为
unique_ptr<T>(new T(std::forward<Args>(args)...))
那会给你
std::shared_ptr<C> ptr = std::make_unique<C>();
哪个输出
C::new() -> 0xf34c20
C::delete() -> 0xf34c20
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)