简体   繁体   English

shared_ptr和C ++中的引用

[英]shared_ptr and references in C++

References in C++ are a conveneint construct that allow us to simplify the following C code: C ++中的引用是一个convneint结构,允许我们简化以下C代码:

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. 共享指针是C ++中另一种简化内存管理的便利。 However, I am not sure how to pass a shared_ptr to a function like f(object& o) which accepts arguments by reference? 但是,我不知道如何将shared_ptr传递给f(object& o)这样的函数,该函数通过引用接受参数?

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? 当通过引用函数传递其对象时,共享指针是否会递增?

Take a shared_ptr by value, and the reference count will increase. 按值获取shared_ptr ,引用计数将增加。 This is easier when you typedef it: 当你这种情况很容易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);
}

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: 永远记得保持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);
}

I think you should prefer to pass smart pointers as references when possible, to avoid extraneous increments and decrements (and copies and whatnot). 我认为您应该尽可能将智能指针作为引用传递,以避免无关的增量和减量(以及副本和诸如此类的东西)。

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);
}
 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. p的引用计数器始终等于1。 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* (). shared_ptr的引用计数器计算指向同一对象的shared_ptr实例的数量,它不跟踪通过调用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 (). 并且它不必 - 因为p保证一直存在到作用域结束并且函数调用处于同一范围(或更深) p将在整个f ()调用期间存在。 So everything is OK. 一切都好。

... unless in f you take the address of o and store somewhere that will last after f returns. ...除非在f中你取o的地址并存储在f返回后会持续的地方。 This you should avoid by all means - pass the shared_ptr if you need to do that. 这应该避免 - 如果需要,请传递shared_ptr。

First things first, from a functionality point of view, references in C++ are exactly the same as pointers. 首先,从功能的角度来看,C ++中的引用与指针完全相同。 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) (例如,允许一个人写一个+ b而不是&a +&b)

Your C and C++ code samples are absolutely not equivalent. 您的C和C ++代码示例绝对不相同。 The C version of your C++ code would be: 您的C ++代码的C版本将是:

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. 实际上,这是C ++编译器在概念上生成的代码。

With regards to your second question: Yes, that is the correct way to call the function f. 关于你的第二个问题:是的,这是调用函数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. 将传递指向该对象的实际指针,就像您没有使用shared_ptr一样。 It is safe however, as long as f isn't doing anything funky. 然而,只要f没有做任何时髦的事情,这是安全的。 Just remember that the same thing exactly is happening as if f's parameter took a pointer instead of a reference. 请记住,确实发生了同样的事情,好像f的参数采用了指针而不是引用。 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). 我个人不喜欢通过引用传递变量(尽管传递const引用是好的)。 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 和平

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM