Pergunta

As referências no C ++ são uma construção conveneint que nos permitem simplificar o seguinte código C:

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

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

para

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

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

ponteiros compartilhados são outra conveniência em C ++ que o gerenciamento de memória simplificar. No entanto, não estou certo de como passar uma shared_ptr para uma função como f(object& o) que aceita argumentos por referência?

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

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

Será que o ponteiro compartilhada ser incrementado quando seu objeto é passado por referência a uma função?

Foi útil?

Solução

Dê uma shared_ptr por valor, e a contagem de referência vai aumentar. Isto é mais fácil quando você typedef-lo:

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

Mantenha em referências mente são aliases. Quando você passar por referência, você não está passando ponteiros, cópias, etc ..., você está aliasing outro objeto. (Na realidade, eles são implementados como ponteiros):

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

Lembre-se sempre para ser const correta, para evitar erros:

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

Eu acho que você deve preferir passar ponteiros inteligentes como referência quando possível, para evitar incrementos estranhos e diminui (e cópias e outros enfeites).

Outras dicas

Será que o ponteiro compartilhada ser incrementado quando seu objeto é passado por referência a uma função?

Não, como você está acessando o ponteiro cru e, em seguida, passá-lo. Você quer fazer algo semelhante a isto:

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

Será que o ponteiro compartilhada ser incrementado quando o seu objecto é passado por referência para uma função?

No código acima - não. p terá seu contador de referência igual a 1 em todos os momentos. Você pode verificar isso em um depurador. contador de referência do shared_ptr conta o número de casos shared_ptr que apontam para o mesmo objeto, ele não acompanha referências criados pela chamada operador * (). E ele não tem que - uma vez que p é garantido para viver até o final do escopo e a chamada de função é neste mesmo âmbito (ou mais profundo) p será lá durante toda a chamada para f (). Então, tudo é OK.

... a menos que em f você obter o endereço de em algum lugar o e loja que vai durar depois de f retornos. Isto deve-se evitar por todos os meios -. Passar o shared_ptr se você precisa fazer isso

As primeiras coisas primeiro, do ponto de vista da funcionalidade, referências em C ++ são exatamente os mesmos como ponteiros. Eles única razão pela qual eles foram adicionados à linguagem era fazer a sintaxe de sobrecarga de operadores ser mais natural. (Por exemplo, para permitir a escrever a + b em vez de & a + & b)

Seu C e amostras de código C ++ não são absolutamente equivalente. A versão C do seu código C ++ seria:

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

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

Na verdade, este é o tipo de código que o compilador C ++ irá gerar conceitualmente.

Com relação à sua segunda pergunta: Sim, essa é a maneira correta de chamar a função f. O contador de ponteiro compartilhada não será incrementado. O ponteiro real para o objeto será passado, como se você não estivesse usando um shared_ptr. É seguro no entanto, contanto que f não está fazendo nada funk. Basta lembrar que a mesma coisa exatamente está acontecendo como se o parâmetro de f tomou um ponteiro em vez de uma referência. A única diferença é que o compilador passa automagicamente o endereço da variável sem você ter que usar explicitamente o operador &.

Eu, pessoalmente, não gosto de nunca passar variáveis ??por referência (passagem por referência const é ok embora). Eu prefiro usar um ponteiro em vez desde que torna mais claro no site da chamada que a função que estamos chamando potencialmente pode modificá-lo de argumento (uma vez que o & símbolo é visível no site da chamada).

Paz

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top