Вопрос

Ссылки в 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);
}

Будет ли увеличиваться общий указатель, когда его объект передается по ссылке в функцию?

Это было полезно?

Решение

Возьмите 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);
}

Я думаю, что вы должны предпочесть передавать умные указатели в качестве ссылок, когда это возможно, чтобы избежать посторонних приращений и уменьшений (а также копий и прочего).

Другие советы

  

Будет ли общий указатель увеличиваться при передаче его объекта по ссылке на функцию?

Нет, так как вы получаете доступ к необработанному указателю и затем передаете его. Вы хотите сделать что-то похожее на это:

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

Будет ли увеличен общий указатель   когда его объект передается по ссылке   к функции?

В приведенном выше коде - нет. У p счетчик ссылок всегда будет равен 1. Вы можете проверить это в отладчике. Счетчик ссылок shared_ptr подсчитывает количество экземпляров shared_ptr, которые указывают на один и тот же объект, он не отслеживает ссылки, которые вы создаете, вызывая operator * (). И в этом нет необходимости - поскольку p гарантированно доживет до конца области действия, а вызов функции находится в той же области (или глубже), p будет во время всего вызова f (). Так что все в порядке.

... если только в f вы не берете адрес o и сохраняете его где-то, что будет работать после возвращения f . Этого вам следует избегать - передайте shared_ptr, если вам нужно это сделать.

Прежде всего, с точки зрения функциональности ссылки в 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.Счетчик общего указателя не будет увеличиваться.Фактический указатель на объект будет передан, как если бы вы не использовали общий_ptr.Однако это безопасно, пока f не делает ничего странного.Просто помните, что происходит то же самое, как если бы параметр f принимал указатель вместо ссылки.Единственное отличие состоит в том, что компилятор автоматически передает адрес переменной без необходимости явного использования оператора &.

Лично мне не нравится передавать переменные по ссылке (хотя передача по константной ссылке вполне допустима).Вместо этого я предпочитаю использовать указатель, поскольку он дает понять в месте вызова, что функция, которую мы вызываем, потенциально может изменить свой аргумент (поскольку символ & виден в месте вызова).

Мир

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top