以下两段代码之间是否有任何差异?他们中的任何一个比另一个好吗?
运算符=
boost::shared_ptr<Blah> foo; // foo.ptr should be NULL
foo = boost::shared_ptr<Blah>(new Blah()); // Involves creation and copy of a shared_ptr?
重置
boost::shared_ptr<Blah> foo; // foo.ptr should be NULL
foo.reset(new Blah()); // foo.ptr should point now to a new Blah object
注意:我需要定义shared_ptr,然后将其设置在不同的行中,因为我在一段代码中使用它,如:
boost::shared_ptr<Blah> foo;
try
{
foo.reset...
}
foo...
答案 0 :(得分:15)
operator=
将shared_ptr
分配给shared_ptr
,而reset
使shared_ptr
获得指针的所有权。所以,基本上你发布的例子没有区别。也就是说,您应该不喜欢它们,只需使用make_shared
:
foo = boost::make_shared<Blah>();
此外,如果可能,您可以通过将try-catch块包装在一个单独的函数中来阻止必须在没有初始化的情况下声明shared_ptr
,该函数只是将shared_ptr
返回给新创建的对象:
boost::shared_ptr<Blah> createBlah() {
try {
// do stuff
return newBlah;
}
catch ...
}
答案 1 :(得分:3)
operator=
将另一个shared_ptr
作为参数,从而创建另一个副本(并提高引用计数),而reset()
获取指针和可选的删除器,因此实际上创建了一个新的shared_ptr在当前的一个之上。
reset相当于(可能实现为)
void reset(T p, D d)
{
shared_ptr shared(p,d);
swap( shared );
}
operator=
可能会实现为:
shared_ptr& operator=( shared_ptr const& other )
{
shared_ptr shared(other);
swap(other);
return *this;
}
这两个函数类似,它们释放对已经包含的内容的控制权(如果有的话),并改为管理不同的指针。
答案 2 :(得分:2)
foo.reset(p)
定义为等同于shared_ptr(p).swap(foo)
。
分配在逻辑上等同于复制和交换,并且可能以这种方式实现。因此foo = shared_ptr(p);
相当于foo.swap(shared_ptr(p))
。如果编译器有一个非常糟糕的一天,可能会有一个额外的副本。
所以在你给出的例子中,我认为他们之间没有多少选择。可能还有其他重要的情况。但是重置会对模板构造函数执行的静态类型p
进行相同的基于模板的捕获,因此,只要获得正确的删除器,就可以了解它。
分配的主要用途是,您希望复制以前存在的shared_ptr
,以共享同一对象的所有权。当然,从临时分配时它也可以正常工作,如果你看一下不同的reset
重载,它们会镜像不同的构造函数。所以我怀疑你可以用任何一种方式实现同样的目标。
答案 3 :(得分:0)
赋值运算符从现有的共享对象创建一个新的共享对象,递增引用计数
GetCompletedTask()
虽然重置调用不会创建新的共享对象,而是新的所有权 - 附加到新的底层指针(通过控制对象)
CSharedObj& CSharedObj::operator=(CSharedObj& r) noexcept
{
if(*this != r){
//detach from the previous ownership
if(0 == dec()) delete m_pControlObj;
//attach to the new control object and increment the reference count
r.inc();
m_pControlObj = r.m_pControlObj;
}
return *this;
}