Java에서 참조로 통과하는 것과 C에서 포인터를 통과하는 것의 차이점은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/600651

문제

나는 몇 달 동안 Java를 공부 해 왔으며 이제 C를 배우기 시작했습니다.

나는 약간 혼란스러워서, 나는 참조로 물체를 전달하고 그 객체에 대한 포인터를 전달한다는 인상을 받았다. 나는 차이가 Java에서 모든 객체를 통과하는 모든 객체가 포인터로 완료된다는 것이었다. C는 실제로 여기저기서 별표와 앰퍼 샌드를 실제로 뿌려야합니다. 최근 대화에서 나는 차이가 있다고 확신했다!

참조로 통과하는 것과 포인터 통과의 차이점은 무엇입니까?

도움이 되었습니까?

해결책

Java도 마찬가지입니다 ...도 아니다 C는 통과 회의를 가지고 있습니다. 그들은 모두 엄격하게 통과합니다.

Pass-by-reference 시맨틱은 메소드에서 매개 변수의 값을 변경할 때 발신자가 인수의 변화를 볼 수 있음을 의미합니다.

자, 당신은 생각하고있을 것입니다. "하지만 그건 Java의 경우입니다! 방법 중에 객체를 변경하면 발신자는 그 변화를 봅니다." 객체는 매개 변수가 아닙니다. 매개 변수는입니다 단지 변수 - 그리고 해당 변수의 값을 변경하면 발신자는이를 볼 수 없습니다. 예를 들어:

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

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

매개 변수가 있다면 진짜 참조로 통과하고 y 나중에 널이 될 것입니다. 대신,의 가치 y 단지 참조 일 뿐이며 그 참조는 가치로 전달됩니다. "참조"라는 단어가 두 용어로 이루어지기 때문에 혼란 스럽지만 다른 것들이 있기 때문입니다.

당신은보고 싶을 수도 있습니다 C# 매개 변수 통과에 관한 내 기사 Java라면 가능한 것이 무엇인지 확인합니다 했다 C#이 할 때 (그리고 언제) ref 예어.

댓글을보고 싶을 수도 있습니다. 내 스택 오버 플로우 답변 주제와 관련이 있습니다.

다른 팁

차이점은 Java에서 모든 객체를 통과하는 모든 객체가 포인터를 자동으로 수행한다는 것입니다. C에서와 같이 실제로 여기저기서 약간의 별표와 앰퍼 샌드를 뿌려야합니다.

임신, 그게 옳습니다. 우리가 pedantic이라면 (그리고 그것이 좋은 일이라면), 우리는 객체가 Java에서 전혀 통과되지 않는다고 말할 수도 있습니다. 전달되는 것은 항상 "포인터"일 뿐이며, Java에서는 참조라고합니다. 모든 간접이 자동으로 수행됩니다. 따라서 C에서 "objref.foo"대신 "objref-> foo"를 할 때는 포인터로 작업하기 때문에 점을 사용할 수 없습니다. Java에서는 다른 점을 알지 못하기 때문에 점을 사용할 수 있습니다. 어쨌든 회원에 액세스하십시오. C에서는 포인터를 전달할 수 있습니다 (여기, 여기, 그것은 ~이다 실제로 포인터라고 불립니다) 그리고 객체 자체를 전달할 수 있으며,이 경우 사본이 전달됩니다. C에서는 스타 또는 "->"를 사용하여 간접적으로 포인터가 지칭하는 객체에 액세스합니다. Java에서는 어쨌든 객체에 액세스하는 유일한 방법은 DOT (objref.member)를 사용하는 것입니다.

우리가 다시 한 번 과도하게 (지금은 더 중요하다), 자바 나 C에는 "참조로 통과"가 없다. 우리가 Java로 전달하는 것은 객체에 대한 참조/포인터이며 C에서는 객체의 사본을 전달하거나 (명백한 경우) 또는 객체에 대한 포인터의 사본 만 다시 전달합니다. 따라서 두 경우 모두 Java와 C- 우리가 전달하는 것은 객체의 주소입니다. Java와 C로 복사 된 원시 Java 유형에 대해 이야기하지 않음 - C에서 주소를 전달할 수 있지만 집계 유형 (즉 구조물)과 C의 "원시 유형"사이에는 차이가 없습니다. 저것 관심.

차이점은 미묘합니다. 어셈블리 수준에서 두 경우 모두 객체의 주소가 함수로 전달됩니다. 그러나 포인터의 경우 파라미터는 대상 객체 (*pch = 'x')를 수정하는 데 사용할 수있는 독립 포인터입니다 (*pch = 'x') 또는 다른 객체 (pch = "newstr")에 액세스 할 수 있습니다. 참조 케이스에서 매개 변수는 대상 객체에 자동으로 간 것으로 나타납니다.

포인터는 참조가 포함 된 변수라고 생각합니다. 함께 & 당신은 메모리 방향 (참조)을 얻을 수 있으며 * 메모리 방향의 내용에 액세스 할 수 있습니다. 나는 책을 제안한다 C 프로그래밍 언어 .

문안 인사

진실 통과 참조 참조에 새 값을 할당 할 수 있으며이 새 값은 내부 호출 메소드와 같이 호출 컨텍스트에서 표시됩니다.

Java에서는 불가능합니다 객체 참조는 가치별로 전달됩니다.

몇 가지

  • C는 참조가 없습니다 (C ++에도 불구하고)
  • 자바에는 포인터가 없습니다
  • 포인터와 참조의 차이점은 포인터가 실제로 계산할 수있는 메모리 주소라는 것입니다. 참조는 계산할 수 없습니다
  • Java 및 C Pass By Value (Java에서 객체를 전달할 때 참조가 함수에 복사됩니다).

C (C ++가 아닌)를 공부하는 경우 참조가 없습니다.

C에서 "Pass By Reference"라는 용어는 단순히 값이 저장 될 주소로 포인터를 전달하여 함수가 값을 변경할 수 있음을 의미합니다. 그렇지 않으면, 당신은 값으로 전달되는데, 이는 변수의 사본이 스택에 생성되고 수정이 영향을 미치지 않음을 의미합니다.

여러 가지면에서 이것은 Java에서 보는 것과 유사합니다. Java에서는 사물을 포인터로 바꾸거나 불평 할 필요가 없다는 점을 제외하고. 다시 말해, 포인터를 전달하면 주소가 스택에 복사되므로 기능이 가리키는 데이터가 아닌 포인터가 변경되면 기능을 수행하면 변경 사항이 사라집니다. 마찬가지로 Java에서 객체 참조를 전달할 때 객체의 내용 (예 : 함수 호출)을 변경할 수 있지만 Anothr 객체를 가리키기 위해 변수를 변경하면 출발 한 후에는 영향을 미치지 않습니다.

C ++ (C처럼 보이는)를 사용하는 경우 참조로 전달할 수 있습니다.이 경우 포인터를 처리 할 필요가 없으며 기능의 변수를 변경하면 실제로 외부 값을 직접 변경합니다 (제외한 제외. 다른 것을 가리킬 수는 없습니다).

Eric Lippert의 최근 기사가 이것에 관한 기사가 있습니다. 그는 C# 컴파일러의 프로그래머이지만, 그가 말하는 것은 Java와 같은 다른 GC 언어로 확장하기에 충분한 일반성이 있습니다.

http://blogs.msdn.com/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx

기사에서 인용 :

포인터는 참조보다 엄격하게 "더 강력합니다. 포인터로 할 수있는 참조로 할 수있는 모든 것. [...

포인터는 일반적으로 주소로 구현됩니다. 주소는 프로세스의 전체 가상 주소 공간 인 "바이트 배열"으로 오프셋 인 숫자입니다. [...

이러한 모든 이유 때문에 우리는 참조를 사양의 주소로 설명하지 않습니다. 이 사양은 단지 기준 유형의 변수가 "참조를 저장"하고 그 구현 방법에 대해 완전히 모호합니다. 마찬가지로, 포인터 변수는 객체의 "주소"를 저장합니다. 참조는 주소와 동일하다고 말하지 않습니다.

따라서 C#에서 참조는 객체를 참조 할 수있는 모호한 것입니다. 반박을 제외하고는 참조로 아무것도 할 수 없으며 평등에 대한 다른 참조와 비교할 수 없습니다. 그리고 C#에서 포인터는 주소로 식별됩니다.

참조와는 대조적으로 주소가 포함 된 포인터로 훨씬 더 많은 작업을 수행 할 수 있습니다. 주소는 수학적으로 조작 될 수 있습니다. 당신은 서로를 빼고 정수를 추가 할 수 있습니다. 그들의 법적 운영은 프로세스의 가상 주소 공간 인 "배열"으로 인덱스하는 "멋진 숫자"임을 나타냅니다.

C/C ++에 익숙한 독자들은 아마도 객체 참조가 포인터와 유사하다는 것을 알았을 것입니다. 이 의심은 본질적으로 정확합니다. 객체 참조는 메모리 포인터와 유사합니다. Java의 안전의 주요 차이점은 실제 포인터를 할 수있는대로 참조를 조작 할 수 없다는 것입니다. 따라서, 객체 참조가 임의의 메모리 위치를 가리키거나 정수처럼 조작 할 수는 없습니다.

  • Java는 지원되지 않고 운영자가 아닌 Java에서 객체 주소를 얻을 수있는 방법입니다.
  • Java에서 참조는 예를 들어 객체에 의해 수행됩니다

MyClass Object1 = new MyClass ();

MyClass Object2 = Object1;

즉, Object1과 Object2는 별도의 객체와 별개의 객체를 참조한다고 생각할 수 있습니다. 그러나 이것은 잘못 될 것입니다. 대신,이 조각이 실행되면 Object1 및 Object2는 동일한 객체를 참조합니다. 다른 사람이 다른 효과를 바꾸면 다른 사람이 변경됩니다.

*초기화 후 객체 주소를 변경할 수 없습니다. 즉, myclass obj = new myclass (); C ++의 참조로 객체와 함께 객체 인스턴스 값 만 변경할 수 있습니다.

참고 : Java는 특수한 기능 Object1이 NULL로 설정되었지만 Object2는 원래 객체를 가리 킵니다.

Java에 대해 잘 모르겠지만 C# 또는 vb.net에서는 가치를 통해 또는 Retrence로 통과 할 수 있습니다.

Retrence에 의해 전달 된 예

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

x는 1과 같지만 x가 foo를 호출하고 x를 x로 전달할 때 x가 foo로 증가하면 원래 값도 증가합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top