7

C++ 中的引用是一种方便的构造,它允许我们简化以下 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++ 中简化内存管理的另一个便利。但是,我不确定如何将 a 传递给通过引用接受参数shared_ptr的函数?f(object& o)

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

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

当它的对象通过引用传递给函数时,共享指针会增加吗?

4

4 回答 4

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);
}

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

于 2009-09-09T22:51:36.043 回答
2

当它的对象通过引用传递给函数时,共享指针会增加吗?

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

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

int main(){
  shared_ptr<object> p (new object());
  f(p);
}
于 2009-09-09T22:47:47.823 回答
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 。

于 2009-09-09T23:21:41.500 回答
-1

首先,从功能的角度来看,C++ 中的引用与指针完全相同。它们被添加到语言中的唯一原因是使运算符重载的语法更自然。(例如允许一个人写 a+b 而不是 &a+&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 的参数采用指针而不是引用一样,完全相同的事情正在发生。唯一的区别是编译器会自动传递变量的地址,而无需显式使用 & 运算符。

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

和平

于 2009-09-09T23:10:55.827 回答