2011-01-19 3 views
1

예를 들어, PHP에서 우리는 다음과 같이 쓸 수 있습니다 :"참조"가 사용되는 방식에 모호성이 있습니까?

class C { 
    var $x; 

    function __construct($x) { 
     $this->x = $x; 
    } 

    function __toString() { 
     return (string)$this->x; 
    } 
} 

function f1($obj) { 
    $obj->x = 2; 
} 

$a = new C(1); 
f1($a); 
echo $a; // 2 

을 그리고 어떤이가 당신이 그들의 속성을 수정할 수 있기 때문에 객체가 참조에 의해 전달되며, 이러한 변경 사항이 클래스의 외부에 반영되어 나타냅니다 것을 말할 것입니다. 즉, 객체는 프리미티브가 복사되는 방식으로 복사되지 않는다.

그러나 우리는 이것을 쓸 수 있습니다 : 이제 객체가 전혀 참조에 의해 전달되지 제안

function f2($obj) { 
    $obj = new C(2); 
} 


$b = new C(1); 
f2($b); 
echo $b; // 1 

합니다. 실제로는, 객체는 복사 (즉, 값에 의해 전달)되지만 은 깊지 않다.- 복사 됨; $obj이 복사되지만 $x은 여전히 ​​동일한 것을 말합니다.

"참조"라는 단어가 두 가지 의미로 사용되었다는 이야기를 들었습니다. 어떤 사람들은 PHP가 참조로 전달된다고 말하고, 다른 이들은 값으로 전달한다고 말합니다.

function f3(&$obj) 

같은 함수를 정의 말할 때

우리는 PHP가 참조로 패스라고 말한다면, 우리는 무엇을 의미합니까? 함수는 객체에 대한 참조를 취합니다. 이것은 첫 번째 의미가 잘못되었음을 나타냅니다.

하지만 C++과 structs 같은 언어는 어떨까요? 내 C++은 녹슬지 만, 클래스 전체를 전달할 때 전체 클래스가 실제로 복사된다고 믿는다. 그래서 가능하다면 함수가 참조를 취하도록하거나 포인터를 사용하도록 권장한다. C#에서는 구조체와 클래스가 어떻게 전달되는지에 차이가 있습니다.

값으로 전달하지 않으면이 딥 복사 동작을 무엇이라고 부릅니까?

우리에게는 3 가지 행동과 2 가지 문구가있어 이들을 묘사하는 것처럼 보입니다. 이로 인해 커뮤니티에 많은 혼란이 생깁니다.

지옥, 나는 당신이 나에게 내가 틀린 무엇인가 썼다라고 나에게 이야기하기를 기다리고있다. 요약


, 3 개 동작은 다음과 같습니다

  1. 객체가 깊은 복사 (객체와 속성이 복제됩니다)
  2. 만 개체가 복사됩니다 (속성은 여전히 ​​참조입니다 우리는 t을 각각 호출해야 무슨 목적은 모든

기술적으로 복사되지 않습니다

  • 메모리의 같은 덩어리) 행동을 hese? 지나가 다-???

  • +0

    (아마 여부) 언젠가, PHP 인수를위한'const' 키워드를 구현하는 것, 이것은 어떠한 모호성을 제거합니다 ... :) – netcoder

    답변

    0

    변수와 개체에 대한 참조를 구분해야하는 두 가지 사항이 있습니다. $ obj 매개 변수에 다른 값을 할당하지 않는 한 함수 외부와 완전히 동일한 객체를 처리합니다. 다른 객체를 할당 한 후에는 변수가 변경되었지만 객체에 대한 참조 만 변수에 전달했기 때문에 외부의 변수는 원래 객체를 가리키고 있습니다.

    1

    만약 내 druthers했다. NET에서 "개체 참조"라는 용어는 개체가 루틴으로 전달되는 대부분의 경우, 개체 - id는 값에 의해 전달됩니다 (개체 ID가 참조로 전달되는 Dictionary.TryGetValue와 같은 경우도 있음). object-id 및 매개 변수 전달 형식을 설명하는 데 동일한 용어를 사용하면 혼동을 초래할 수 있습니다.

    1

    C++에서 처음 두 개는 모두 값에 의한 전달이라고합니다. 딥 카피가 발생하는 정도는, 문제가되는 클래스의 카피 시멘틱스에 의존합니다. 이것들은 프로그래머에 의해 지정 될 필요가 있습니다 (일부의 클래스는 자원에의 핸들이며, 얕은 카피가 필요합니다. 대부분의 컨테이너 등의 깊이는 깊어 야합니다) - 복사 됨). 파이썬에는 깊고 얕은 복사를위한 라이브러리 함수가 있습니다. 딥 복사는 때때로 복제 (cloning)라고 불립니다. C++ 및 Java

    세 번째를 참조로 전달이라고합니다. 이것은 피 호출자에 의해 수정 될 수있는 무언가를 전달하는 일반적인 용어입니다.

    이 (가 참조하는 개념이 없습니다 만, 패스로 포인터하는 패스에 의해 참조와 거의 동일하므로 C는이 규칙에 대한 예외입니다.) 첫 번째

    +0

    @downvoter : 설명해주십시오. –

    2

    먼저 가지 : 당신은 할 수 있습니다 References Explained을 읽으십시오.


    일반적으로 변수는 항상 값에 의해 전달됩니다. 중요한 것은 가치가 실제로 무엇인지입니다.

    "개체를 보유하고 있습니다"변수는 개체에 대한 참조를 보유합니다. 당신이 객체

    function foo($bar) {} 
    

    참조 같은 함수 정의가있을 때

    따라서, 전달됩니다. 그래서 당신이 물건을 바꿀 수 있습니다.

    그러나 함수 내의 변수에 새 값을 할당하면 참조를 다른 것으로 덮어 쓰는 것만으로도 해당 참조를 잃게됩니다.

    변수에 $someVar을 전달하면 $bar$someVar은 동일한 값 (즉 참조)을 갖지만 메모리에 자체 위치가 있습니다.

    하기 전에 :

    $someVar -> object_reference ┐ 
    
               ├ -> object 
    
    $bar  -> object_reference ┘ 
    

    후 :

    $someVar -> object_reference -> object 
    
    
    
    $bar  -> other_value 
    

    이제 함수 정의는 다음

    function foo(&$bar) {} 
    

    같은 경우, 당신은 실제로에 참조를 전달 위치 다른 변수의 메모리.

    foo($someVar)으로 함수를 호출하면 $bar$someVar과 같은 위치를 가리 킵니다. 즉, 새 값을 할당하면 메모리의 특정 위치를 덮어 쓰게됩니다.

    하기 전에 :

    $someVar ┐ 
    
          ├ -> object_reference -> object 
    
    $bar  ┘ 
    

    후 :

    $someVar ┐ 
    
          ├ -> other_value   object 
    
    $bar  ┘ 
    
    +0

    그럼 ... 그 질문에 답하십시오. 니가 말하는거야, 뭐야? 객체는 * 객체 참조를 통해 전달되고, 다른 경우에는 * 참조를 메모리 *에 전달합니다. 그리고 프리미티브는 무엇입니까? 아니면 딥 복사 된 객체입니까? 두 시나리오 모두에서 "참조"라는 단어를 사용 했으므로 정규화되지 않은 경우 애매한 점에 동의하게됩니다. – mpen

    +0

    @ 마크 :이 용어는 모호하지 않습니다. 동일한 개념을 설명하기 때문에이 두 용어 모두에서 용어를 사용하는 것이 옳습니다. 매개 변수가'&'기호로 정의되지 않으면 함수가 참조를 허용한다고 결코 말할 수 없습니다. 그리고 물건을 건네 주면 속성을 수정할 수 있다는 것을 알고 있습니다. 두 번째 예제에서는 전달 된 개체의 속성에서 작업하지 않지만 변수에 새 값을 할당한다는 점에 유의하십시오. 참조는 다른 것을 유일하게 정의하는 것입니다. 다른 OO 언어에서도 동일한 동작을 발견하게됩니다. –

    +0

    @ 마크 : 죄송합니다. 이해할 수없는 방식으로 설명 할 수 없으면 죄송합니다. –