php4와 php5에서 다음 코드의 차이가 왜 생기는지 궁금합니다.

vudghkzm의 이미지

아래 코드는 php4 환경하에서 구동시킨 코드 입니다.

<?php

class Test
{
    var $a = 'GG';
}
 
$test = new Test();

$assigned = $test;
$reference =& $test;

$test->a = 'GL';
$test = NULL;

var_dump( $test );
echo( '<br>' );
var_dump( $reference );
echo( '<br>' );
var_dump( $assigned );
echo( '<br>' );

?>

출력 결과는 다음과 같습니다.

NULL 
NULL 
object(test)(1) { ["a"]=> string(2) "GG" } 

아래 코드는 php5 환경하에서 구동시킨 코드 입니다.

<?php

class Test
{
         public $a = 'GG';
}

$test = new Test();

$assigned = $test;
$reference =& $test;

$test->a = 'GL';
$test = NULL;

var_dump( $test );
echo( '<br>' );
var_dump( $reference );
echo( '<br>' );
var_dump( $assigned );
echo( '<br>' );

?>

출력 결과는 다음과 같습니다.

NULL 
NULL 
object(Test)#1 (1) { ["a"]=> string(2) "GL" }

php5에서 객체에 대한 연산자 = 의 개념이 달라진거 같은데요..
위에서 php5코드에서 보면 왜 test 객체의 a 값의 변화는 $assigned에 반영되었는데, $test = NULL; 은 $assigned에 반영되지 않는건지 궁금합니다.

우수한의 이미지

사실 객체쪽 문제는 PHP4가 보편적이지 않은 방식으로 작동하던 것이었다고 합니다.
PHP5에서는 PHP4와 달리
객체 자체를 복사해서 생성하는 것이 아니라,
객체에 대한 핸들을 복사해서 생성한다고 합니다.
이것은 '참조'와는 다른 개념이라고 하네요.

PHP4에서
$test = new test(); // 핸들#1
$assigned = $test; // 핸들#1
$reference =& $test; // 핸들#1

PHP5에서
$test = new test(); // 핸들#1 : 객체가 있는 메모리 주소를 가리킴
$assigned = $test; // 핸들#2 : 객체가 있는 메모리 주소를 가리킴
$reference =& $test; // 핸들#1 : $test가 있는 메모리 주소를 가리킴
$test = NULL; // 객체가 있는 메모리 주소를 가리키지 않음

http://kr.php.net/manual/en/language.oop5.basic.php
여길 참조하세요. (특히 맨아래쪽 코멘트)

그런데 결과가 저랑 다르군요. 전 PHP5에서도 $assigned->a는 GG라고 나옵니다.

우수하지 않아요. '우수한'은 옛날 만화 CityHunter에서 따와서 쓰던 별명. ;-)

progcom의 이미지

PHP 내부 객체를 다룰 때, 메모리 복사가 일어나는가의 문제입니다.
직접 PHP 소스를 분석해보면 쉽게 알 수 있기는 하지만... 간단히 설명하자면,

PHP 4에서의 객체는 '배열(Array)'하고 똑같다고 보면 됩니다. 배열에서 함수 테이블만 추가된 형태이지요.
$assigned = $test;
가 실행 될 때, $assigned에 $test의 모든 내용이 '복사'됩니다. 이 시점에서 $assigned와 $test가 가르키는 메모리 주소 공간이 다르게 됩니다.

PHP 5에서는 우수한님 말씀대로 '핸들'이라는 개념을 넣어서 다룹니다.
$assigend = $test;
가 실행 될 때에, $test와 동일한 주소 공간을 가르키는 '포인터'를 하나 더 생성한다고 보면 됩니다. $test가 가르키는 공간의 내용이 변경되면, $assigned가 가르키는 공간도 동일하기에, $assigned로 접근해도 변경된 내용이 적용됩니다.

참고로, PHP 5에서 PHP 4와 동일한 동작을 하기 위해서는 (객체 복사)
$assigned = clone $test;
라고 쓰시면 되고, PHP 4와 PHP 5에서 동일하게 호환성 있는 코드를 만드려면, 객체에 대해서 참조(reference)를 사용해서 프로그램하는게 좋습니다. (PHP 4에서는 무조건 복사가 일어나므로, 참조를 이용하는게 메모리도 절약하는 방법입니다)

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.