PHP에서 객체를 생성할 때, =와 =&의 차이점에 대해서...
php를 공부하던중 =와 =&에 대해서 이상한 차이점을 발견하여 글을 올리게 되었습니다.
<?php $GLOBALS['TA'] = ""; class A { var $str; function A($str) { $this->str = $str; $GLOBALS['TA'] =& $this; } }; // 복사에 의한 대입 $e = new A("E1"); var_dump($GLOBALS['TA']); $e->str = "E2"; var_dump($GLOBALS['TA']); // 참조에 의한 대입 $r =& new A("R1"); var_dump($GLOBALS['TA']); $r->str = "R2"; var_dump($GLOBALS['TA']); ?> == 결과 == $ php -f t2.php object(a)(1) { ["str"]=> string(2) "E1" } object(a)(1) { ["str"]=> string(2) "E1" } object(a)(1) { ["str"]=> string(2) "R1" } object(a)(1) { ["str"]=> string(2) "R2" } $
전 지금까지는 두가지 다 동일한 코드라 생각했고, 보통 $n = new Class; 쪽을 선호해 왔는데(보통 =로 쓰라고 추천하더군요), 오늘 코딩하면서 이상하게 객체가 둘로 갈라지는 현상이 보여서 문제점을 찾다가 위와 같은 현상을 발견하게 되었습니다. 제가 의도한 동작은 생성자에서 전역변수 TA에 객체의 참조를 저장하는 것인데, = 로 대입하면 객체가 두개가 생성이 되어서 서로 연결이 되지 않더군요;;;
그렇다면, new로 새로운 객체를 만들때는 반드시 =&로 대입해 줘야 한다는 얘기가 됩니다. 만약 위의 경우처럼 생성자에서 전역변수에 자기자신을 등록한다던가 하는 일을 하게 되면 문제가 생길 수 있기 때문입니다.
다른 분들은 이 문제에 대해서 어떻게 생각하십니까? 위와 같이 new로 객체를 생성할 때 =를 써야 된다고 생각하십니까? 혹은 =&을? 제가 보기엔 =& 쪽이 일반적으로 C++에서 쓰이는 것과 같은 의미가 되므로 이쪽이 더 바람직한 것 같습니다만...
ps. 참고로, 제가 만들던 클래스는 다음과 같습니다. 생성자와 소멸자가 상속이 되도록(혹은 상속시에 좀 더 편하게 부모 클래스의 생성자와 소멸자를 호출할 수 있도록) 하고, 만약 프로그래머가 소멸자를 호출하지 않았을 경우에는 자동으로 소멸자를 선언된 순서의 역순으로 호출해 주도록 하는 기반 클래스 입니다. *.Test.php는 이 클래스의 테스트 프로그램으로, 소멸자가 2번(프로그래머에 의해서 1번, destroyObject() 함수에 의해서 1번) 호출되었을때의 동작을 보여주는 프로그램입니다.
BaseObject.php :
<?php $GLOBALS['_transient']['DestructorList'] = array(); function registerDestructor($ref, $funcname) { var_dump($ref); array_unshift( $GLOBALS['_transient']['DestructorList'], array(&$ref, $funcname) ); } function destroyObject() { foreach ($GLOBALS['_transient']['DestructorList'] as $obj) { if ( is_object($obj[0]) && method_exists($obj[0], $obj[1]) ) { if ( !isset($obj[0]->isDestroyed) || !$obj[0]->isDestroyed ) { $obj[0]->{$obj[1]}(); } } } } register_shutdown_function('destroyObject'); //////////////////////////////////////////////////////////////////////////////// class BaseObject { var $errNo; var $errMsg; var $isDestroyed; function BaseObject() { $args = func_get_args(); call_user_func_array(array(&$this, "_constructor"), $args); } function _constructor($s = "Default") { registerDestructor(&$this, "_destructor"); $this->errNo = 0; $this->errMsg = ""; $this->isDestroyed = false; } function _destructor() { $this->isDestroyed = true; echo "[OK" . $this->isDestroyed . "]<br />\n"; } function setErr($no, $msg) { $this->errNo = $no; $this->errMsg = $msg; } }; ?>
BaseObject.Test.php :
<?php include_once("BaseObject.php"); class AA extends BaseObject { var $str_; function _constructor($a = "Default") { parent::_constructor(); $this->str_ = $a; } function _destructor() { echo "Destructor AA($this->str_)<br />\n"; parent::_destructor(); } function p() { echo "[" . $this->str_ . "]<br />\n"; } }; //////////////////////////////////////////////////////////////////////////////// class AAA extends AA { function _constructor($a = "Default") { parent::_constructor($a); } function _destructor() { $this->isDestroyed = true; echo "Destructor AAA($this->str_)<br />\n"; parent::_destructor(); } }; //////////////////////////////////////////////////////////////////////////////// $c =& new AAA("3"); $c->_destructor(); echo "========<br />\n"; ?>
PHP 에서 $a =&$b 는 레퍼런스 입니다.C++ 의 경우
PHP 에서 $a =&$b 는 레퍼런스 입니다.
C++ 의 경우 int& a = b; 이런식인것 과 같죠
PHP의 $a = $b 는 복사입니다.
PHP 5 에서는 object 는 $a = $b 하면 기본적으로 레퍼런스가 될거라고 했는데 사용안해봐서 모르겠군요.
$a = new class; 를 C의 개념으로 생각하시는 것 같은데
이때는 new class 를 하면 임시 객체가 생기고 $a 에 복사를 하는 그런게
아닙니다. $a 가 바로 new class 가 되는거죠.
[quote="devilhero"]$a = new class; 를 C
저도 그렇게 알고 있었고, 그래서 늘 $a = new class;의 형태로 써 왔는데 위의 예제에서는 다음과 같이 동작합니다.
그렇지 않으면 위의 예제코드가 설명되지 않습니다. 물론 속도는 일반적인 상식과는 다르게 참조인 =&보다 = 쪽이 빠르다고 들었습니다.
저는 =&를 사용합니다. fastcgi모드로 돌려보면 메모리 사용
저는 =&를 사용합니다. fastcgi모드로 돌려보면 메모리 사용량이 틀립니다. PHP는 클래스 뿐만 아니라 모든 변수의 참조 전달이 복사보다 느리다고 알려져 있는데 클래스가 커지면 참조가 훨씬 가벼워집니다.. 저는 대부분의 함수의 리턴도 참조로 전달받고 뭐.. 그렇습니다 =_=;
$a=&addslashes($b); 이런식으로요..
http://kr.php.net/manual/kr/language.oop
http://kr.php.net/manual/kr/language.oop.newref.php
댓글 달기