Pergunta

Eu tenho estudado Java por alguns meses e agora estou começando a aprender C.

Estou um pouco confuso, eu estava sob a impressão de que passar um objeto por referência e passar um ponteiro para esse objeto eram a mesma coisa: Eu pensei que a diferença era que em Java tudo passagem de objetos é feita com ponteiros automaticamente, onde, como em C tem de se efectivamente regar pequenas asteriscos e ampersands aqui e acolá. Recentemente, em uma conversa, eu estava certo de que havia uma diferença!

O que é a diferença entre passando por referência e passar um ponteiro?

Foi útil?

Solução

Nem Java nem C tem passagem por referência. Ambos são estritamente passar por valor.

passagem por referência semântica significa que quando você alterar o valor do parâmetro no método, o chamador vai ver que a mudança no argumento.

Agora, você pode estar pensando: "Mas isso é o caso em Java Se eu mudar um objeto durante o método, o chamador vê que a mudança!". O objeto não é o parâmetro O parâmetro é apenas a variável -. E se você alterar o valor dessa variável, o chamador não ver isso. Por exemplo:

public void foo(Object x)
{
    x = null;
}

public void caller()
{
    Object y = new Object();
    foo(y);
    // y is still not null!
}

Se o parâmetro foram realmente passado por referência, y seria nula depois. Em vez disso, o valor de y é apenas uma referência, e que a referência é passado por valor. É confuso porque a palavra "referência" é tanto em termos, mas são coisas diferentes.

Você pode querer olhar em meu artigo sobre parâmetro C # passando para ver o que seria possível se o Java fez tem passagem por referência semântica, como C # faz quando (e somente quando) você usa a palavra-chave ref.

Você também pode querer olhar para os comentários para minha resposta Stack Overflow relacionado com o tema.

Outras dicas

Eu pensei que a diferença era que em Java tudo passagem de objetos é feita com ponteiros automaticamente, quando, como no C se tem que realmente polvilhe pequenos asteriscos e ampersands aqui e ali.

conceptivo, isso é certo. Se formos pedante (e isso é uma coisa boa), podemos mesmo dizer objetos não são passados ??em tudo em Java. O que é passado é sempre apenas o "ponteiro", que em Java é chamado de referência. Todos indireto é feito automaticamente. Então, quando você faz "objref-> foo" em vez de "objref.foo" em C e não pode usar o ponto porque você trabalha com um ponteiro, em Java você ainda pode usar o ponto porque não sei mais nada a membros de acesso de qualquer maneira. Em C, você pode passar o ponteiro (e aqui, é realmente chamado ponteiro) e você pode passar o objeto em si, caso em que uma cópia é passado. Em C, você acessar o objeto de que um ponteiro se refere a por engano usando a estrela ou "->". Em Java, a única maneira objetos são acessados ??de qualquer maneira está usando o ponto (objref.member).

Se estamos pedante novamente (agora mais importante de novo), nem em Java nem em C não é "passar por referência". O que nós passamos em Java é a referência / ponteiro para o objeto e, em C que quer passar uma cópia do objeto (caso óbvio) ou passamos novamente apenas uma cópia de um ponteiro para o objeto. Assim, em ambos os casos - Java e C - o que passam são os endereços dos objetos. Não falar sobre tipos Java primitivos, que são copiados em Java e C - mesmo que você pode passar o seu endereço em C também, não há diferença entre um tipo de agregado (ou seja, um struct) e um "tipo primitivo" em C em < em> que respeito.

As diferenças são sutis. A um nível de montagem, em ambos os casos o endereço do objecto é passado para a função. No entanto, no caso do ponteiro parâmetro é um ponteiro independente, que pode ser usado para modificar o objecto alvo (PCH = * 'x') ou pode ser usado para aceder a um objecto diferente (PCH = "newstr"). No caso de referência, o parâmetro é automaticamente indirected ao objeto de destino.

Eu acredito que um ponteiro é uma variável que contém uma referência. Com o & você pode obter um sentido de memória (de referência) e com * você pode acessar o conteúdo de uma direção de memória. Eu sugiro o livro A Linguagem de Programação C .

Saudações

passar por referência meios que você pode atribuir um novo valor para a referência, e este novo valor será visível no contexto de chamada, assim como no interior chamado método.

Em Java, isso não é possível, porque referências a objetos são passados ??por valor .

Algumas coisas

  • C não tem referências (apesar de C ++)
  • Java não tem ponteiros
  • A diferença entre ponteiros e referências é, que os ponteiros são praticamente endereços de memória você pode calcular com. As referências não podem ser calculados com
  • Java e C passar por valor (Ao passar um objecto em Java, a referência é copiada para a função)

Se você está estudando C (em vez de C ++), então não há referências.

O termo "passagem por referência" em C significa simplesmente que você está passando um ponteiro como o endereço em que o valor será armazenado, para que a função pode alterar seu valor. Caso contrário, você está passando por valor o que significa que uma cópia da variável é gerada na pilha e modificações não têm impacto.

De muitas formas isso é semelhante ao que você vê no Java, exceto que em Java você não tem que virar explicitamente as coisas em um ponteiro ou dereference eles. Em outras palavras, quando você passa um ponteiro, o endereço é copiado na pilha, por isso, se a sua função altera o ponteiro (em vez dos dados aponta para), as alterações desaparecem quando você é feito com a função. Da mesma forma, quando você passar uma referência de objeto em Java, você pode alterar o conteúdo do objeto (por exemplo, chamando funções), mas alterando o varialbe ao ponto em anothr objeto não terá nenhum efeito uma vez que você sair.

Se você estiver usando C ++ (que se parece com C), então você pode passar por referência, caso em que você não precisa lidar com ponteiros, e alterações na variável na função realmente mudar o valor externo diretamente ( Só que você não pode fazê-lo apontar para outra coisa).

Há um recente artigo de Eric Lippert sobre isso. Ele é um programador do compilador C #, mas o que ele diz que não tem generalidade suficiente para ser estendido a outras línguas GC tais como Java:

http: // blogs .msdn.com / ericlippert / Arquivo / 2009/02/17 / referências-são-não-addresses.aspx

citar o artigo:

Os ponteiros são estritamente "mais poderoso" do que referências; qualquer coisa que você pode fazer com referências que você pode fazer com ponteiros. [...]

Os ponteiros são geralmente implementadas como endereços. Um endereço é um número que é um deslocamento para a "matriz de bytes" que é todo o espaço de endereços virtuais do processo. [...]

Por todas estas razões que não descrevem referências como endereços na especificação. A especificação apenas diz que uma variável do tipo de referência "armazena uma referência" para um objeto, e deixa-lo completamente vago quanto à forma que possam ser implementadas. Da mesma forma, a variável armazena ponteiro "endereço" de um objeto, que por sua vez, fica muito vago. Em nenhum lugar se diz que as referências são os mesmos endereços.

Assim, em C # uma referência é uma vaga coisa que lhe permite fazer referência a um objeto. Você não pode fazer nada com uma referência exceto dereference-lo, e compará-lo com outra referência para a igualdade. E em C # um ponteiro é identificado como um endereço.

Em contraste com uma referência, você pode fazer muito mais com um ponteiro que contém um endereço. Os endereços podem ser manipulados matematicamente; você pode subtrair um do outro, você pode adicionar inteiros para eles, e assim por diante. Suas operações legais indicam que eles são "números de fantasia" que índice para a "array", que é o espaço de endereço virtual do processo.

Os leitores familiarizados com C / C ++ provavelmente notou que o objeto referências aparecem ser semelhante aos ponteiros. Essa suspeita é, essencialmente, correto. Uma referência é objecto semelhante a um ponteiro de memória. A principal diferença, ea chave para Java segurança-é que você não pode manipular referências como você pode ponteiros reais. Assim, você não pode causar uma referência de objecto para apontar para uma localização de memória arbitrária ou manipulá-lo como um número inteiro.

  • java não é suportado operador & então como u pode obter o endereço objeto em Java.
  • Em referência java é feito por objeto, por exemplo,

MyClass object1 = new MyClass ();

MyClass object2 = object1;

i. você pode pensar que object1 e Object2 referem-se a separar e objetos distintos. No entanto, isso seria errado. Em vez disso, após esta executa fragmento, object1 e object2 irá referir-se tanto para o mesmo objecto. se você mudar em qualquer outro efeito.

* voce não pode mudar o endereço do objeto depois initialize i.e. MyClass obj = new MyClass (); como referência em C ++, com objeto que você pode mudar apenas o valor objeto de instância

Nota: Java fornecem uma característica especial object1 foi definido como nulo, mas aponta ainda Object2 ao objeto original.

i não tenho certeza sobre java, mas em C # ou VB.net você pode passar por valor ou por refrence

exemplo passando por refrence

    static void Main(string[] args)
    {
        int x = 1;
        Foo(ref x);
        Console.WriteLine(x.ToString());//this will print 2
    }

    private static void Foo(ref int x)
    {
        x++;
    }

Observe que x é igual a 1, mas quando você chamar o método Foo e passando x por refrence quando x é aumentada de um em Foo o valor original é aumentada demasiado

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