是make_shared真的比新的更有效吗? [英] Is make_shared really more efficient than new?
问题描述
我正在尝试使用C ++ 11中的 shared_ptr
和 make_shared
,并编写了一个玩具示例,实际上是在调用 make_shared
时发生的。作为基础设施,我使用llvm / clang 3.0以及XCode4中的llvm std c ++库。
class Object
{
public:
Object(const string& str)
{
cout< 构造器<< str<< endl;
}
Object()
{
cout< Default constructor<< endl;
}
〜Object()
{
cout< Destructor< endl;
}
Object(const Object& rhs)
{
cout< 复制构造函数...< endl;
}
};
void make_shared_example()
{
cout< 使用make_shared创建smart_ptr ...< endl;
auto ptr_res1 = make_shared< Object>(make_shared);
cout<< 使用make_shared:done创建smart_ptr。 << endl;
cout<< 创建smart_ptr使用新...< endl;
auto ptr_res2(new Object(new));
cout<< 使用new:done创建smart_ptr。 << endl;
}
现在看看输出,请:
使用make_shared ...创建smart_ptr
构造函数make_shared
复制构造函数...
复制构造函数...
破坏者
使用make_shared:done创建smart_ptr。
smart_ptr using new ...
构造函数new
使用new:done创建smart_ptr。 b
$ b解构函数
析构函数
看来 make_shared
正在调用复制构造函数两次。如果我为一个 Object
使用常规新
分配内存,这不会发生,只有一个对象
构建。
我想知道的是以下内容。我听说 make_shared
应该比使用 new
[1],[2]更有效。一个原因是因为 make_shared
将引用计数与要在同一内存块中管理的对象一起分配。好的,我得到了点。这当然比两个单独的分配操作更有效。
相反,我不明白为什么这必须伴随着对复制构造函数的两次调用的成本 帮助和解释为什么 - [1] http://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared [ 2] http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/ STL11-Magic-Secrets (约分钟10) EDIT 你是对的,输出不匹配发布的代码。代码应该是 第二个 作为基础设施,我使用llvm / clang 3.0以及llvm std XCode4中的c ++库。 这似乎是你的问题。 C ++ 11标准规定 需要:表达式:: new(pv)T(std :: forward(args) 。),其中pv的类型为void *,并指向适合保存类型为T的对象的存储,应该很好地形成。 A应是分配器(17.6.3.5)。 A的复制构造函数和析构函数不会抛出异常。 所以你得到的结果与标准不一致。 LLVM的libc ++在这方面被打破了。提交错误报告。 以下是将代码加入VC2010时发生的情况: 我建议提交一个错误报告,因为libc ++的行为坏了。 I was experimenting with Now have a look at the output, please: 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 It appears that What I am wondering about is the following. I heard that On the contrary I don't understand why this has to come with the cost of two calls to the copy constructor of Can you help and explain why -- [1] http://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared [2] http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/STL11-Magic-Secrets (around minute 10) EDIT You are right, the output does not match the code posted. the code should rather be The second As infrastructure I was using llvm/clang 3.0 along with the llvm std c++ library within XCode4. Well that appears to be your problem. The C++11 standard states the following requirements for 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. So the results you get are not consistent with the standard. LLVM's libc++ is broken in this regard. File a bug report. For reference, here's what happened when I took your code into VC2010: I also ported it to Boost's original I'd suggest filing a bug report, as libc++'s behavior is broken. 这篇关于是make_shared真的比新的更有效吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! Object
。因为这个,我不相信 make_shared
比在 中使用 new
> case。我错了吗?好的,可以实现 Object
的移动构造函数,但仍然不确定这是否比分配对象$ c更有效$ c>到
new
。至少不是在每一种情况。如果复制 Object
比为参考计数器分配内存更便宜,这是真的。但是 shared_ptr
- 内部引用计数器可以使用几个原始数据类型实现,<?p>
make_shared
是效率的方式去,尽管概述了副本开销?
void make_shared_example()
{
cout< 使用make_shared创建smart_ptr ...< endl;
auto ptr_res1 = make_shared< Object>(make_shared);
cout<< 使用make_shared:done创建smart_ptr。 << endl;
cout<< 创建smart_ptr使用新...< endl;
shared_ptr< Object> ptr_res2(new Object(new));
cout<< 使用new:done创建smart_ptr。 << endl;
}
auto
是一个错误。抱歉,
make_shared< T>
(和 allocate_shared
)的以下要求第20.7.2.2.6节:
不是需要是可复制构造的。事实上,
T
甚至不需要为非展示位置新的可构造。它只需要在现场可构造。这意味着 make_shared< T>
可以使用 T
的只有 / code>它就位。
使用make_shared创建smart_ptr ...
构造函数make_shared
使用make_shared:done创建smart_ptr。
使用new ...创建smart_ptr
构造函数new
使用new:done创建smart_ptr。
析构函数
析构函数
我也将它移植到Boost的原始 shared_ptr
和 make_shared
,我得到了与VC2010相同的东西。
shared_ptr
and make_shared
from C++11 and programmed a little toy example to see what is actually happening when calling make_shared
. As infrastructure I was using llvm/clang 3.0 along with the llvm std c++ library within XCode4.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;
auto ptr_res2(new Object("new"));
cout << "Create smart_ptr using new: done." << endl;
}
make_shared
is calling the copy constructor two times. If I allocate memory for an Object
using a regular new
this does not happen, only one Object
is constructed.make_shared
is supposed to be more efficient than using new
[1], [2]. One reason is because make_shared
allocates the reference count together with the object to be managed in the same block of memory. OK, I got the point. This is of course more efficient than two separate allocation operations.Object
. Because of this I am not convinced that make_shared
is more efficient than allocation using new
in every case. Am I wrong here? Well OK, One could implement a move constructor for Object
but still I am not sure whether this this is more efficient than just allocating Object
through new
. At least not in every case. It would be true if copying Object
is less expensive than allocating memory for a reference counter. But the shared_ptr
-internal reference counter could be implemented using a couple of primitive data types, right?make_shared
is the way to go in terms of efficiency, despite the outlined copy overhead? 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;
}
auto
was a mistake. Sorry about that.
make_shared<T>
(and allocate_shared<T>
), in section 20.7.2.2.6:
T
is not required to be copy-constructable. Indeed, T
isn't even required to be non-placement-new constructable. It is only required to be constructable in-place. This means that the only thing that make_shared<T>
can do with T
is new
it in-place.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
shared_ptr
and make_shared
, and I got the same thing as VC2010.