C++ 中的shared_ptr 和引用

发布于 2024-08-04 18:28:59 字数 576 浏览 8 评论 0原文

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++ 中简化内存管理的另一个便利之处。但是,我不确定如何将 shared_ptr 传递给像 f(object& o) 这样通过引用接受参数的函数?

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

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

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

References in C++ are a conveneint construct that allow us to simplify the following C code:

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

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

to

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

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

Shared pointers are another convenience in C++ that simplify memory management. However, I am not sure how to pass a shared_ptr to a function like f(object& o) which accepts arguments by reference?

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

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

Will the shared pointer be incremented when its object is passed by reference to a function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

请别遗忘我 2024-08-11 18:28:59

按值获取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);
}

我认为您应该更喜欢在可能的情况下将智能指针作为引用传递,以避免无关的增量和减量(并且副本等等)。

Take a shared_ptr by value, and the reference count will increase. This is easier when you typedef it:

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

Keep in mind references are aliases. When you pass by reference, you're not passing pointers, copies, etc..., you're aliasing another object. (In reality they are implemented as pointers):

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!
}

Always remember to be const correct, to prevent errors:

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

I think you should prefer to pass smart pointers as references when possible, to avoid extraneous increments and decrements (and copies and whatnot).

流星番茄 2024-08-11 18:28:59

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

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

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

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

Will the shared pointer be incremented when its object is passed by reference to a function?

No, as you are accessing the raw pointer and then passing it. You want to do something similar to this:

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

int main(){
  shared_ptr<object> p (new object());
  f(p);
}
月亮邮递员 2024-08-11 18:28:59
f(object&o){
  //做某事
}

int main(){
  Shared_ptr<对象>; p(新对象());
  f(*p);
}

共享指针会递增吗
当它的对象通过引用传递时
到一个函数?

在上面的代码中 - 不。 p 的引用计数器始终等于 1。您可以在调试器中验证这一点。 shared_ptr的引用计数器计算指向同一对象的shared_ptr实例的数量,它不跟踪您通过调用operator*()创建的引用。而且它不必 - 因为 p 保证存活到作用域结束,并且函数调用位于同一作用域(或更深) p 将是在对 f() 的整个调用过程中。所以一切都好。

...除非在 f 中,您获取 o 的地址并将其存储在 f 返回后持续存在的位置。您应该无论如何避免这种情况 - 如果您需要这样做,请传递shared_ptr。

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

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

Will the shared pointer be incremented
when its object is passed by reference
to a function?

In the code above - no. p will have its reference counter equal to 1 at all times. You can verify this in a debugger. shared_ptr's reference counter counts the number of shared_ptr instances that point to the same object, it doesn't track references you create by calling operator* (). And it doesn't have to - since p is guaranteed to live until the end of the scope and the function call is in this same scope (or deeper) p will be there during the entire call to f(). So everything is OK.

... unless in f you take the address of o and store somewhere that will last after f returns. This you should avoid by all means - pass the shared_ptr if you need to do that.

好倦 2024-08-11 18:28:59

首先,从功能的角度来看,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 引用传递是可以的)。我更喜欢使用指针,因为它使调用站点更清楚地表明我们正在调用的函数可能会修改它的参数(因为 & 符号在调用站点是可见的)。

和平

First things first, from a functionality point of view, references in C++ are exactly the same as pointers. They only reason they were added to the language was to make the syntax of operator overloading be more natural. (For example to allow one to write a+b instead of &a+&b)

Your C and C++ code samples are absolutely not equivalent. The C version of your C++ code would be:

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

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

In fact, this is the kind of code that your C++ compiler will conceptually generate.

With regards to your second question: Yes, that is the correct way to call the function f. The shared pointer counter will not be incremented. The actual pointer to the object will be passed, as if you were not using a shared_ptr. It is safe however, as long as f isn't doing anything funky. Just remember that the same thing exactly is happening as if f's parameter took a pointer instead of a reference. The only difference is that the compiler automagically passes the address of the variable without you having to explicitly use the & operator.

I personally do not like to ever pass variables by reference(passing by const reference is ok though). I prefer to use a pointer instead since it makes it clearer at the call site that the function that we are calling may potentially modify it's argument(since the & symbol is visible at the call site).

Peace

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文