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
댓글 달기