gpt4 book ai didi

c++ - make_shared 真的比 new 更高效吗?

转载 作者:IT老高 更新时间:2023-10-28 14:00:40 24 4
gpt4 key购买 nike

我正在用 C++11 中的 shared_ptrmake_shared 进行试验,并编写了一个小玩具示例来查看调用 make_shared 时实际发生的情况>。作为基础架构,我使用 llvm/clang 3.0 以及 XCode4 中的 llvm std c++ 库。

class Object
{
public:
Object(const string& str)
{
cout << "Constructor " << str << endl;
}

Object()
{
cout << "Default constructor" << endl;

}

~Object()
{
cout << "Destructor" << endl;
}

Object(const Object& rhs)
{
cout << "Copy constructor..." << endl;
}
};

void make_shared_example()
{
cout << "Create smart_ptr using make_shared..." << endl;
auto ptr_res1 = make_shared<Object>("make_shared");
cout << "Create smart_ptr using make_shared: done." << endl;

cout << "Create smart_ptr using new..." << endl;
shared_ptr<Object> ptr_res2(new Object("new"));
cout << "Create smart_ptr using new: done." << endl;
}

现在请看一下输出:

Create smart_ptr using make_shared...

Constructor make_shared

Copy constructor...

Copy constructor...

Destructor

Destructor

Create smart_ptr using make_shared: done.

Create smart_ptr using new...

Constructor new

Create smart_ptr using new: done.

Destructor

Destructor

似乎 make_shared 正在调用复制构造函数两次。如果我使用常规 newObject 分配内存,则不会发生这种情况,只会构造一个 Object

我想知道的是以下内容。我听说 make_shared 应该比使用 new( 1 , 2 ) 更有效。一个原因是因为 make_shared 将引用计数与要在同一内存块中管理的对象一起分配。好的,我明白了。这当然比两个单独的分配操作更有效。

相反,我不明白为什么这必须伴随着两次调用Object 的复制构造函数的代价。因此,我不相信 make_shared 比在 every 情况下使用 new 分配更有效。我在这里错了吗?好吧,可以为 Object 实现一个移动构造函数,但我仍然不确定这是否比通过 new 分配 Object 更有效.至少不是在所有情况下。如果复制 Object 比为引用计数器分配内存更便宜,那将是正确的。但是shared_ptr-内部引用计数器可以使用几个原始数据类型来实现,对吧?

您能帮忙解释一下为什么 make_shared 是提高效率的方法,尽管概述了复制开销?

最佳答案

As infrastructure I was using llvm/clang 3.0 along with the llvm std c++ library within XCode4.

嗯,这似乎是你的问题。 C++11 标准规定了 make_shared<T> 的以下要求(和 allocate_shared<T> ),在第 20.7.2.2.6 节中:

Requires: The expression ::new (pv) T(std::forward(args)...), where pv has type void* and points to storage suitable to hold an object of type T, shall be well formed. A shall be an allocator (17.6.3.5). The copy constructor and destructor of A shall not throw exceptions.

T 不需要是可复制构造的。确实,T甚至不需要是非放置新的可构造的。它只需要可就地构建。这意味着唯一的 make_shared<T>可以用 Tnew它就地。

所以你得到的结果不符合标准。 LLVM 的 libc++ 在这方面被破坏了。提交错误报告。

作为引用,以下是我将您的代码导入 VC2010 时发生的情况:

Create smart_ptr using make_shared...
Constructor make_shared
Create smart_ptr using make_shared: done.
Create smart_ptr using new...
Constructor new
Create smart_ptr using new: done.
Destructor
Destructor

我还将它移植到了 Boost 的原始 shared_ptrmake_shared ,我得到了和VC2010一样的东西。

我建议提交一个错误报告,因为 libc++ 的行为被破坏了。

关于c++ - make_shared 真的比 new 更高效吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9302296/

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