gpt4 book ai didi

c++ - 为什么 'std::make_shared' 始终使用全局内存分配,即使类重载 new/delete 运算符也是如此?

转载 作者:行者123 更新时间:2023-12-02 03:59:57 24 4
gpt4 key购买 nike

当使用std::make_shared<C>时不会调用类重载的 new/delete 运算符。

当使用std::shared_ptr<C>时, std::unique_ptr<C> & std::make_unique<C>使用类重载的 new/delete 运算符。

查看文档时,它是完全正确的并且有详细记录。

cppreference解释行为:

std::make_shared uses ::new, so if any special behavior has been set up using a class-specific operator new, it will differ from 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 运算符。

那么,这种行为的理由是什么?

并且,详细说明 std::make_shared 的 C++ 规范在哪里?行为?

感谢您的帮助。

最佳答案

So, what is the rational of the behavior?

这样做的原因是因为 make_shared 不仅分配您的对象,它还分配 shared_ptr 的控制 block 。为了使其尽可能高效,它调用一次 new 并一次性为控制 block 和对象分配足够的存储空间。否则,它必须调用 new 两次,这会使分配开销加倍。

如果您想使用自定义分配器,那么您需要使用 std::allocate_shared它将使用您的自定义分配器进行一次内存获取来创建 shared_ptr

<小时/>

另一种选择是使用 std::make_unique 创建一个 unique_ptr,然后使用它来初始化 shared_ptr。这是可行的,因为 unique_ptr 没有控制 block ,因此 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

关于c++ - 为什么 'std::make_shared' 始终使用全局内存分配,即使类重载 new/delete 运算符也是如此?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57929127/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com