2012-05-15 2 views
13

배열을 사용하여 트리를 통해 경로를 저장하는 스택으로 사용하고 있습니다. 각 요소는 트리의 노드를 가리키고 마지막 요소를 끈 다음 해당 요소가 참조하는 객체를 null로 설정하려고합니다. PHP는 C 틱 언어 수행으로 '*'연산자를 가지고 있다고 가정PHP에서 참조를 역 참조 할 수 있습니까?

$node = array_pop($path); 
*$node = null; 

:

기본적으로

. 지금은 내가했다 아이 부모 노드와 기억하기에서 시작하여 다음과 같이 null로 그 설정의 추악한 솔루션이 있습니다

if($goLeft) { 
    $parent->left = null; 
} else { 
    $parent->right = null; 
} 

을 나는 경로를 포함하는 어레이가에 의해 생성되기 때문에이 추한 말 내 트리 클래스의 공용 함수. 나는 PHP의 특이성 (feature?)을 다루는 구현 세부 사항을 노출시키지 않고 트리를 통과하는 경로의 노드에서 직접 작업하는 기능을 폭로하고 싶습니다. ATM 반환 값 (이 경우 $ goLeft)에 부울을 포함 시켜서 참조를 역 참조 할 수없는 문제를 해결할 수 있습니다.

이 문제가 두 번째 발생 했으므로 누구나 코드 블록의 첫 번째 블록과 비슷한 기능을 수행 할 수있는 방법을 알고 있다면 공유하십시오.

(EDIT) & 's 및 배열의 ​​많은 순열 실험 후

, 그것은 기본적인 문제는 내가지고 있다고 오류의 원인을 잘못 해석했다는 것을 밝혀졌습니다.

나는
$a = ($x > $y) ? &$foo[$bar] : $blah; 

을 시도하고 "구문 오류, 예기치 않은 '&'"있어요. 나는이 문제가 $foo[$bar]에 & - 운영자를 사용하고 있음을 의미한다고 해석했습니다. 그 범인은 정확히

if($x > $y) { 
    $a = &$foo[$bar]; 
} else { 
    $a = null; 
} 

과 같이 완벽하게 작동합니다. 그래서 나는 존재하지 않았던 문제에 대한 해결 방법을 찾고있는 야생 거위 쫓아 갔다. 내가 &의 체인을 깨지 않는 한, PHP는 내가 원하는 것을 수행한다. 이것은 변수 (변수 자체가 아님)가 참조하는 객체를 조작하는 것이다. 나를 엉망이 무엇 예

$a1 = new SomeClass; 
$a2 = &$a1; 
$a3 = &$a2; 
$a4 = &$a3; 

$a4 = 42; // This actually sets $a1 to 42 
var_dump($a1); // Emits 42 

내가 (이것은 잘못된 것입니다) 객체 어쨌든 참조로 주변에 전달되는 생각, 그래서 표현이 개체에 해결하면 나는 &이 필요하다고 생각하지 않았다이다. 내 말은 :

class A { 
    public $b; 
} 

class B {} 

$a = new A; 
$a->b = new B; 

$c1 = $a->b; 
$c2 = &$a->b; 

$c1 = 42; // Merely assigns 42 to $c1 
$c2 = 42; // Assigns 42 to $a->b 

이 정확한 문제는 http://www.php.net/manual/en/language.oop5.references.php에 있습니다. 내가 그것을 읽었을 때 처음으로 침몰했으면 좋겠어!

+1

잘 모르겠어, 네가 원하지만'$ parent-> left = null; 대신에'unset ($ parent-> left); '를 쓸 수있다. – Leri

+4

@PLB : 언 세트 (unset) '가 아니라'연결 해제 (unlink) '. –

+1

@Rocket 물론 그렇습니다. 나는 매우 피곤하다. – Leri

답변

7

매우 흥미로운 질문입니다! 해결 방법을 찾았을 수도 있습니다. & 연산자를 사용하여 배열에 객체 참조를 채우는 경우 해당 배열 값을 NULL으로 설정하여 원래 객체를 삭제할 수 있습니다. array_pop에 의해 반환 된 변수를 사용하는 대신 어레이에서 직접 연산해야합니다. 그런 다음 배열을 팝하여 그 위치를 자유롭게 할 수 있습니다 (그러면 그 값은 NULL 값을 포함합니다).

이 무슨 뜻인지 (로켓의 코드를 기반으로)입니다 : PHP에서

$a=(object)'a'; 
$b=array(&$a); 
$b[0] = NULL; 
// array still contains an element 
array_pop($b); 
// now array is empty 
var_dump($a); // NULL 

http://codepad.org/3D7Lphde

+0

와우, 네. 그것은 실제로 작동합니다! –

+0

@bfavaretto : 당신이 해결했습니다! 굉장하고, 아주 간단합니다! 나는 내가 원하는 것을 할 수있는 더 예쁜 방법이 있다는 것을 자랑스럽게 생각한다. 모든 도움을 주셔서 감사합니다, 스택 오버플로 규칙! – kahulio

+0

ㅎ - 집에 오기 전에 누군가가 거기에 도착할 줄 알았어 야했다. 나는 속임수를 쓰고있다. – CD001

0

array_pop() 반환 값을 지정하지 마십시오.

php > $test = array(1, 2, 3); 
php > $test2 = array(0 => &$test[0], 1 => &$test[1], 2 => &$test[2]); 
php > array_pop($test2); 
php > var_dump($test); 
array(3) { 
    [0]=> 
    &int(1) 
    [1]=> 
    &int(2) 
    [2]=> 
    int(3) 
} 
php > var_dump($test2); 
array(2) { 
    [0]=> 
    &int(1) 
    [1]=> 
    &int(2) 
} 
+0

아닙니다. 그가 원했던 것은 "원래의"객체가 설정되지 않은 것입니다 ('$ test [2]'). 왜'array_pop'의 반환 값이 중요합니까? '$ test2'를 어느 쪽이든 수정하고 있습니다. –

+0

음 ... 설명에서 얻는 것이 어렵습니다. :) – Narf

1

내가 읽은 곳을 기억하고 싶지만 PHP는 주어진 객체에 대한 참조 카운터를 유지함으로써 작동합니다. 일부 노드에 대한 참조가있는 객체 (예 : Tree)가 있습니다. array_pop을 사용하면 노드 객체에 대한 참조가 반환됩니다. 즉, 추가 참조가 만들어 지지만 원래 참조가 여전히 존재합니다.unset 때 갑자기 된 참조, 그 파괴되지만 원래 개체가 파괴되지 않기 때문에 Tree 해당 참조가 여전히 있습니다. 이 객체의 메모리를 해제하는 유일한 방법은 Tree을 개인적으로 파괴하는 것입니다 (두 번째 코드 블록에서 수행중인 것으로 보입니다).

PHP는 메모리 할당 해제 또는 가비지 수집을 강제로 수행 할 수있는 방법이없는 것처럼 보이므로 신중하게 참조를 처리하지 않으면 문제가 발생합니다.

P.S. 수 없습니다 나는 아직도 당신이하려고하는 것에 대해 혼란스러워합니다. Rocket의 설명은 도움이되지만 $path은 무엇이며 두 번째 블록과 어떤 관련이 있습니까?

+0

내 원래의 질문은 지나치게 구체적이라고 생각합니다. 스택과 함께 작업 중이거나 null을 설정하려고해도 실제로 문제가되지 않습니다. 나 자신을 설명하는 것이 더 좋아질 필요가있다. 무언가에 대한 참조를 포함하는 변수가 있다고 가정 해 보겠습니다. 개체, 다른 변수, 중요하지 않습니다. 예 : '$ a = &$b; ' 이제'$ a'에 의해 참조 된 것에 연산을 수행하고 싶습니다.이 경우는'$ b'입니다. 어쩌면'$ b'를 null, 문자열 "alice"또는 다른 객체로 설정하려고합니다. 상관 없어요. 어쨌든, 이것이 내가 성취하려고하는 것입니다. – kahulio

+0

@ kahulio 설명하기가 약간 어렵습니다. 기본적으로,'$ a = & $ b'는'$ a'에서'$ b'까지 기호 테이블 별명을 만듭니다. 즉,'$ a'에하는 일들은'$ b'에 직접적으로 영향을 미칩니다. '$ b'가 객체 인 경우,'$ a = $ b'는 객체 참조를'$ b'에서'$ a'로 복사합니다. 객체'$ a'에 대한 연산은 객체'$ b'와 같은 효과를 갖지만 별도의 심볼 테이블 엔트리입니다. '$ a' ('$ a = 'blah';')에 쓰면'$ b'에 전혀 영향을 미치지 않습니다. 'array_pop'는 참조 (별칭)을 반환하지 않고 반환 할 수 없기 때문에 반환 값을 쓰는 것은 어떤 식 으로든 원래의 객체에 영향을 미치지 않으며 그렇게 할 수도 없습니다. –

0
$one = 1; 
$two = 2; 
$array = array(&$one, &$two); 

// magic 
end($array); 
$array[key($array)] = NULL; 

var_dump($two); 
// NULL 

참조는 객체를 변경할 수 있습니다.

관련 문제