shared_ptr和C ++中的引用

时间:2009-09-09 22:43:06

标签: c++ boost smart-pointers shared-ptr

C ++中的引用是一个convneint构造,允许我们简化以下C代码:

f(object *p){
  //do something
}

int main(){
  object* p = (object*) calloc(sizeof(object));
  f(p);
}

f(object& o){
  //do something
}

int main(){
  object o = object();
  f(o);
}

共享指针是C ++中另一种简化内存管理的便利。但是,我不确定如何将shared_ptr传递给像f(object& o)这样通过引用接受参数的函数?

f(object& o){
  //do something
}

int main(){
  shared_ptr<object> p (new object());
  f(*p);
}

当通过引用函数传递对象时,共享指针是否会递增?

4 个答案:

答案 0 :(得分:10)

按值shared_ptr取值,引用计数将增加。当您typedef时,这会更容易:

typedef boost:shared_ptr<object> object_ptr;

void foo(object_ptr obj)
{
    obj->/* stuff*/;
    obj.reset(); //only resets this local copy, that means:
                 // reduce reference count (back to 1), and
                 // set obj to point at null.
}

int main(void)
{
    object_ptr obj(new object());
    foo(obj);
}

请记住,引用是别名。当您通过引用传递时,您没有传递指针,副本等...,您正在别名另一个对象。 (实际上它们是作为指针实现的):

typedef boost:shared_ptr<object> object_ptr;

void foo(object_ptr& obj)
{
    obj.reset(); // the references was never increased, since a copy has not
                 // been made, this *is* obj in main. so the reference 
                 // goes to 0, and obj is deleted
}

int main(void)
{
    object_ptr obj(new object);
    foo(obj); // after this, obj has been reset!
}

始终记得const正确,以防止错误:

typedef boost:shared_ptr<object> object_ptr;

void foo(const object_ptr& obj)
{
    obj.reset(); // cannot do! 
}

int main(void)
{
    object_ptr obj(new object);
    foo(obj);
}

我认为您应该尽可能将智能指针作为引用传递,以避免无关的增量和减量(以及副本等等)。

答案 1 :(得分:2)

  

当通过引用函数传递对象时,共享指针是否会递增?

不,因为您正在访问原始指针然后传递它。你想做类似的事情:

f(shared_ptr<object> o){
  //do something
}

int main(){
  shared_ptr<object> p (new object());
  f(p);
}

答案 2 :(得分:1)

f(object& o){
  //do something
}

int main(){
  shared_ptr<object> p (new object());
  f(*p);
}
     

共享指针是否会递增   当它的对象通过引用传递时   一个功能?

在上面的代码中 - 没有。 p 的参考计数器始终等于1。您可以在调试器中验证这一点。 shared_ptr的引用计数器计算指向同一对象的shared_ptr实例的数量,它不跟踪通过调用operator *()创建的引用。并且它没有 - 因为 p 保证在范围结束之前存活并且函数调用处于同一范围(或更深) p 将是在整个调用 f ()期间。一切都好。

...除非在 f 中使用 o 的地址并存储在 f 之后将会持续的地方。你应该尽量避免 - 如果你需要这样做,请传递shared_ptr。

答案 3 :(得分:-1)

首先,从功能的角度来看,C ++中的引用与指针完全相同。他们只是将它们添加到语言中的原因是为了使运算符重载的语法更自然。 (例如,允许一个人写一个+ b而不是&amp; a +&amp; b)

您的C和C ++代码示例绝对不相同。您的C ++代码的C版本将是:

f(object *p){
  //do something
}

int main(){
  object o;
  object_constructor(&o);
  f(&o);
  object_destructor(&o);
}

实际上,这是C ++编译器在概念上生成的那种代码。

关于你的第二个问题:是的,这是调用函数f的正确方法。共享指针计数器不会递增。将传递指向该对象的实际指针,就像您没有使用shared_ptr一样。然而,只要f没有做任何时髦的事情,这是安全的。请记住,确实发生了同样的事情,好像f的参数采用了指针而不是引用。唯一的区别是编译器自动传递变量的地址,而不必明确使用&amp;操作

我个人不喜欢通过引用传递变量(尽管传递const引用是可以的)。我更喜欢使用指针,因为它使调用站点更清晰,我们调用的函数可能会修改它的参数(因为&amp;符号在调用站点可见)。

和平