【发布时间】:2012-03-07 07:41:57
【问题描述】:
我正在用 C++11 中的 shared_ptr 和 make_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;
}
现在请看一下输出:
使用 make_shared 创建 smart_ptr...
构造函数 make_shared
复制构造函数...
复制构造函数...
析构函数
析构函数
使用 make_shared 创建 smart_ptr: 完成。
使用 new... 创建 smart_ptr
构造函数新
使用 new: done 创建 smart_ptr。
析构函数
析构函数
make_shared 似乎调用了复制构造函数两次。如果我使用常规new 为Object 分配内存,则不会发生这种情况,只会构造一个Object。
我想知道的是以下内容。听说make_shared应该比new效率更高(1,2)。一个原因是因为make_shared 将引用计数与要在同一内存块中管理的对象一起分配。好的,我明白了。这当然比两个单独的分配操作更有效。
相反,我不明白为什么这必须伴随着两次调用Object 的复制构造函数的代价。因此,我不相信make_shared 在每个 情况下都比使用new 分配更有效。我在这里错了吗?好吧,可以为Object 实现一个移动构造函数,但我仍然不确定这是否比通过new 分配Object 更有效。至少不是在所有情况下。如果复制Object 比为引用计数器分配内存更便宜,那将是正确的。但是shared_ptr-internal 引用计数器可以使用几种原始数据类型来实现,对吧?
您能帮忙解释一下为什么make_shared 在效率方面是要走的路,尽管概述了复制开销?
【问题讨论】:
-
你认为
auto是什么意思? -
在测试 C++11 函数的速度之前,您可能应该在您的类中实现一个 move 构造函数,并使其完全符合 C++11。
-
该代码与输出不匹配。您显示的代码泄漏。
-
这会有什么不同,@Ildjarn?此代码中的任何内容都不应触发移动或任何
Object实例的副本。该代码根本与报告的输出不匹配。 -
@Rob : 除了“应该”之外,如果没有移动构造函数,可能会出现本来应该是移动的副本,因此在没有移动构造函数的情况下计算副本是没有意义的。
标签: c++ shared-ptr clang libc++ make-shared