downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

참조가 아닌 것> <참조란 무엇인가
Last updated: Tue, 28 Jul 2009

view this page in

참조는 무엇을 하는가

PHP 참조는 두 변수가 같은 내용을 참조할수 있게 한다. 다음과 같은 일을 한다:

<?php
$a 
=& $b;
?>

$a$b가 같은 내용을 가리키는 것을 의미합니다.

Note: 여기에서 $a$b는 완전히 동일합니다. $a$b를 가리키고, 그 반대일 수도 있습니다. $a$b는 같은 위치를 가리킵니다.

Note: 참조를 가진 배열이 복사되면, 그 값들은 참조인 상태로 남습니다. 이는 배열이 함수에 값으로 넘겨졌을 때에도 유효합니다.

Note: 정의되지 않은 변수를 참조를 통해 할당하거나, 넘기거나, 반환하면 변수가 생성됩니다.

Example #1 정의되지 않은 변수에 참조 사용하기

<?php
function foo(&$var) { }

foo($a); // $a가 "생성되고" null로 할당됩니다

$b = array();
foo($b['b']);
var_dump(array_key_exists('b'$b)); // bool(true)

$c = new StdClass;
foo($c->d);
var_dump(property_exists($c'd')); // boold(true)
?>


같은 문법을 참조를 반환하는 함수나, new 연산자(PHP 4.0.4부터)에도 사용합니다.

<?php
$bar 
=& new fooclass();
$foo =& find_var($bar);
?>

PHP 5부터, new는 자동으로 참조를 반환하므로, 여기에서처럼 =&를 사용하는 것은 배제되었고 E_STRICT 등급 메세지를 발생합니다.

Note: & 연산자를 사용하지않으면 생성된 객체의 복사본을 돌려받는다. 그 클래스에서 $this를 사용한다면 그것은 클래스의 현재 인스턴스에만 영향을 미친다. &가 없는 지정은 인스턴스(즉, 객체)를 복사할것이고 $this는 복사본에만 영향을 미칠것이다. 이와 같은 것은 퍼포먼스와 메모리의 효율적인 사용을 위해 오직 하나의 인스턴스만 취급하기를 원할 경우에 사용된다.
@new처럼 생성자에서 발생하는 모든 에러 메시지를 보이지 않게 하기 위해서 @연산자를 사용할수 있지만, &new구문을 사용할때는 이 연산자는 작동하지 않는다. 이것은 젠드 엔진의 한계로 이런 표현을 쓰면 해석 오류가 발생한다.

Warning

함수 안에서 global로 선언한 변수에 참조를 할당하면, 그 참조는 그 함수 안에서만 보여집니다. 이를 피하려면 $GLOBALS 배열을 사용하십시오.

Example #2 함수 안에서 전역 변수 참조하기

<?php
$var1 
"Example variable";
$var2 "";

function 
global_references($use_globals)
{
    global 
$var1$var2;
    if (
$use_globals) {
        
$var2 =& $var1// 함수 안에서만 보여집니다
    
} else {
        
$GLOBALS["var2"] =& $var1// 전역 문맥에서도 보여집니다
    
}
}

global_references(false);
echo 
"var2 is set to '$var2'\n"// var2 is set to ''
global_references(true);
echo 
"var2 is set to '$var2'\n"// var2 is set to 'Example variable'
?>

global $var;$var =& $GLOBALS['var'];의 단축형임을 생각하십시오. 그러므로 다른 참조를 $var에 할당하는 것은 지역 변수의 참조를 변경할 뿐입니다.

Note: foreach 구문 안에서 참조 변수에 값을 할당하면, 참조도 변경됩니다.

Example #3 참조와 foreach 구문

<?php
$ref 
0;
$row =& $ref;
foreach (array(
123) as $row) {
    
// do something
}
echo 
$ref// 3 - 반복한 배열의 마지막 원소
?>


참조가 하는 두번째 일은 참조에 의해 변수를 전달하는 것이다. 이는 함수에서 지역 변수를 만들거나 같은 내용을 참조하는 호출을 사용하는 변수를 생성함으로써 가능해진다. 예를 들면:

<?php
function foo(&$var)
{
    
$var++;
}

$a=5;
foo($a);
?>

위 코드는 $a를 6으로 만들것이다. 이렇게 되는 이유는 foo함수 안의 변수 $var$a와 같은 내용을 가리키기 때문이다. 이에 대한 정보는 참조에 의한 전달 섹션을 읽어보십시오.

참조가 하는 세번째 일은 참조에 의해 돌려받기이다.



참조가 아닌 것> <참조란 무엇인가
Last updated: Tue, 28 Jul 2009
 
add a note add a note User Contributed Notes
참조는 무엇을 하는가
strata_ranger at hotmail dot com
26-Sep-2009 10:29
An interesting if offbeat use for references:  Creating an array with an arbitrary number of dimensions.

For example, a function that takes the result set from a database and produces a multidimensional array keyed according to one (or more) columns, which might be useful if you want your result set to be accessible in a hierarchial manner, or even if you just want your results keyed by the values of each row's primary/unique key fields.

<?php
function array_key_by($data, $keys, $dupl = false)
/*
 * $data  - Multidimensional array to be keyed
 * $keys  - List containing the index/key(s) to use.
 * $dupl  - How to handle rows containing the same values.  TRUE stores it as an Array, FALSE overwrites the previous row.
 *         
 * Returns a multidimensional array indexed by $keys, or NULL if error.
 * The number of dimensions is equal to the number of $keys provided (+1 if $dupl=TRUE).
 */  
{
   
// Sanity check
   
if (!is_array($data)) return null;
   
   
// Allow passing single key as a scalar
   
if (is_string($keys) or is_integer($keys)) $keys = Array($keys);
    elseif (!
is_array($keys)) return null;

   
// Our output array
   
$out = Array();
   
   
// Loop through each row of our input $data
   
foreach($data as $cx => $row) if (is_array($row))
    {
     
     
// Loop through our $keys
     
foreach($keys as $key)
      {
       
$value = $row[$key];

        if (!isset(
$last)) // First $key only
       
{
          if (!isset(
$out[$value])) $out[$value] = Array();
         
$last =& $out; // Bind $last to $out
       
}
        else
// Second and subsequent $key....
       
{
          if (!isset(
$last[$value])) $last[$value] = Array();
        }

       
// Bind $last to one dimension 'deeper'.
        // First lap: was &$out, now &$out[...]
        // Second lap: was &$out[...], now &$out[...][...]
        // Third lap:  was &$out[...][...], now &$out[...][...][...]
        // (etc.)
       
$last =& $last[$value];
      }
     
      if (isset(
$last))
      {
       
// At this point, copy the $row into our output array
       
if ($dupl) $last[$cx] = $row; // Keep previous
       
else       $last = $row; // Overwrite previous
     
}
      unset(
$last); // Break the reference
   
}
    else return
NULL;
   
   
// Done
   
return $out;
}

// A sample result set to test the function with
$data = Array(Array('name' => 'row 1', 'foo' => 'foo_a', 'bar' => 'bar_a', 'baz' => 'baz_a'),
              Array(
'name' => 'row 2', 'foo' => 'foo_a', 'bar' => 'bar_a', 'baz' => 'baz_b'),
              Array(
'name' => 'row 3', 'foo' => 'foo_a', 'bar' => 'bar_b', 'baz' => 'baz_c'),
              Array(
'name' => 'row 4', 'foo' => 'foo_b', 'bar' => 'bar_c', 'baz' => 'baz_d')
              );

// First, let's key it by one column (result: two-dimensional array)
print_r(array_key_by($data, 'baz'));

// Or, key it by two columns (result: 3-dimensional array)
print_r(array_key_by($data, Array('baz', 'bar')));

// We could also key it by three columns (result: 4-dimensional array)
print_r(array_key_by($data, Array('baz', 'bar', 'foo')));

?>
dnhuff at acm dot org
09-Jun-2008 06:33
In reply to Drewseph using foo($a = 'set'); where $a is a reference formal parameter.

$a = 'set' is an expression. Expressions cannot be passed by reference, don't you just hate that, I do. If you turn on error reporting for E_NOTICE, you will be told about it.

Resolution: $a = 'set'; foo($a); this does what you want.
Drewseph
29-May-2008 11:15
If you set a variable before passing it to a function that takes a variable as a reference, it is much harder (if not impossible) to edit the variable within the function.

Example:
<?php
function foo(&$bar) {
   
$bar = "hello\n";
}

foo($unset);
echo(
$unset);
foo($set = "set\n");
echo(
$set);

?>

Output:
hello
set

It baffles me, but there you have it.
Amaroq
01-Apr-2008 06:56
The order in which you reference your variables matters.

<?php
$a1
= "One";
$a2 = "Two";
$b1 = "Three";
$b2 = "Four";

$b1 =& $a1;
$a2 =& $b2;

echo
$a1; //Echoes "One"
echo $b1; //Echoes "One"

echo $a2; //Echoes "Four"
echo $b2; //Echoes "Four"
?>
charles at org oo dot com
19-Oct-2007 10:59
points to post below me.
When you're doing the references with loops, you need to unset($var).

for example
<?php
foreach($var as &$value)
{
...
}
unset(
$value);
?>
Hlavac
09-Oct-2007 09:25
Watch out for this:

foreach ($somearray as &$i) {
  // update some $i...
}
...
foreach ($somearray as $i) {
  // last element of $somearray is mysteriously overwritten!
}

Problem is $i contians reference to last element of $somearray after the first foreach, and the second foreach happily assigns to it!
dovbysh at gmail dot com
06-Jul-2007 07:50
Solution to post "php at hood dot id dot au 04-Mar-2007 10:56":

<?php
$a1
= array('a'=>'a');
$a2 = array('a'=>'b');

foreach (
$a1 as $k=>&$v)
$v = 'x';

echo
$a1['a']; // will echo x

unset($GLOBALS['v']);

foreach (
$a2 as $k=>$v)
{}

echo
$a1['a']; // will echo x

?>
amp at gmx dot info
08-Jun-2007 05:59
Something that might not be obvious on the first look:
If you want to cycle through an array with references, you must not use a simple value assigning foreach control structure. You have to use an extended key-value assigning foreach or a for control structure.

A simple value assigning foreach control structure produces a copy of an object or value. The following code

$v1=0;
$arrV=array(&$v1,&$v1);
foreach ($arrV as $v)
{
  $v1++;
  echo $v."\n";
}

yields

0
1

which means $v in foreach is not a reference to $v1 but a copy of the object the actual element in the array was referencing to.

The codes

$v1=0;
$arrV=array(&$v1,&$v1);
foreach ($arrV as $k=>$v)
{
    $v1++;
    echo $arrV[$k]."\n";
}

and

$v1=0;
$arrV=array(&$v1,&$v1);
$c=count($arrV);
for ($i=0; $i<$c;$i++)
{
    $v1++;
    echo $arrV[$i]."\n";
}

both yield

1
2

and therefor cycle through the original objects (both $v1), which is, in terms of our aim, what we have been looking for.

(tested with php 4.1.3)
firespade at gmail dot com
03-Apr-2007 02:11
Here's a good little example of referencing. It was the best way for me to understand, hopefully it can help others.

$b = 2;
$a =& $b;
$c = $a;
echo $c;

// Then... $c = 2
php at hood dot id dot au
05-Mar-2007 06:56
I discovered something today using references in a foreach

<?php
$a1
= array('a'=>'a');
$a2 = array('a'=>'b');

foreach (
$a1 as $k=>&$v)
$v = 'x';

echo
$a1['a']; // will echo x

foreach ($a2 as $k=>$v)
{}

echo
$a1['a']; // will echo b (!)
?>

After reading the manual this looks like it is meant to happen. But it confused me for a few days!

(The solution I used was to turn the second foreach into a reference too)
ladoo at gmx dot at
17-Apr-2005 09:05
I ran into something when using an expanded version of the example of pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu below.
This could be somewhat confusing although it is perfectly clear if you have read the manual carfully. It makes the fact that references always point to the content of a variable perfectly clear (at least to me).

<?php
$a
= 1;
$c = 2;
$b =& $a; // $b points to 1
$a =& $c; // $a points now to 2, but $b still to 1;
echo $a, " ", $b;
// Output: 2 1
?>
php.devel at homelinkcs dot com
15-Nov-2004 11:16
In reply to lars at riisgaardribe dot dk,

When a variable is copied, a reference is used internally until the copy is modified.  Therefore you shouldn't use references at all in your situation as it doesn't save any memory usage and increases the chance of logic bugs, as you discoved.
joachim at lous dot org
10-Apr-2003 10:46
So to make a by-reference setter function, you need to specify reference semantics _both_ in the parameter list _and_ the assignment, like this:

class foo{
   var $bar;
   function setBar(&$newBar){
      $this->bar =& newBar;
   }
}

Forget any of the two '&'s, and $foo->bar will end up being a copy after the call to setBar.

참조가 아닌 것> <참조란 무엇인가
Last updated: Tue, 28 Jul 2009
 
 
show source | credits | sitemap | contact | advertising | mirror sites