我正在尝试使用C++11的shared_ptr
和make_shared
,并编写了一个小的玩具示例来查看调用make_shared
时实际发生了什么。作为基础设施,我正在使用带有XCode4的llvm/clang 3.0以及llvm标准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`调用了两次复制构造函数。如果我使用常规的`new`为一个Object分配内存,则不会发生这种情况,只会构造一个Object。使用make_shared创建智能指针...
构造函数make_shared
复制构造函数...
复制构造函数...
析构函数
析构函数
使用make_shared创建智能指针:完成。
使用new创建智能指针...
构造函数new
使用new创建智能指针:完成。
析构函数
析构函数
我想知道的是,为什么`make_shared`被认为比使用`new`更有效(1, 2)。原因之一是因为`make_shared`将引用计数与要管理的对象一起分配在同一块内存中。好的,我明白了。这当然比两个单独的分配操作更有效率。
相反,我不明白为什么这要以调用两次`Object`的复制构造函数为代价。因为这一点,我并不认为在每种情况下使用`make_shared`都比使用`new`更有效。我错了吗?好吧,可以为`Object`实现移动构造函数,但我仍然不确定这是否比仅通过`new`分配`Object`更有效。至少在每种情况下都是正确的。如果复制`Object`比为引用计数器分配内存更便宜,则可能是真的。但是,`shared_ptr`内部的引用计数器可以使用几个原始数据类型来实现,对吗?
您能帮忙解释一下为什么在效率方面`make_shared`是首选,尽管存在上述复制开销吗?
auto
是什么意思? - Kerrek SBObject
实例的移动或复制将被触发。这段代码与报告的输出结果根本不匹配。 - Rob Kennedy