2013-08-23 3 views
0

У меня есть этот PHP кодPHP ссылка на массив

$a = array('one'); 

$b[0] = &$a[0]; 

$c = $a; 

$b[0] = 'three'; 

$a = array('two'); 

var_dump($a); echo '<br/>'; 

var_dump($b); echo '<br/>'; 

var_dump($c); echo '<br/>'; 

, который выводит этот ->

array(1) { [0]=> string(3) "two" } 

array(1) { [0]=> &string(5) "three" } 

array(1) { [0]=> &string(5) "three" } 

$ B и $ а указывает на то же значение, но $ с не должно указывать на то же значение , он должен иметь свою собственную копию значения. Затем, когда я изменяю значение $ b на три, я не понимаю, почему изменяется значение $ c. Как я могу это предотвратить? Кроме того, когда я меняю значение $ a на «два», почему же $ b также не меняется на «два»?

Заранее спасибо.

+0

Что вы пытаетесь достичь? Трудно помочь, если мы не знаем, почему вы делаете ссылки в первую очередь. –

+0

Любой может создать сложный код, который они не понимают. Вместо того, чтобы выяснять, что не работает, почему бы не попробовать на самом деле отгонять то, что вы пытаетесь сделать, и решить эту проблему. О, и не используйте ссылки (как правило) ... – ircmaxell

+0

Это то, что я делаю.Я должен динамически связывать переменные с mysqli_stmt :: bind_result, поэтому я делаю это, для ($ i = 0; $ i <$ n_result; $ i ++) {$ b_res [$ i] = & $ result [$ i] ; } call_user_func_array (array ($ stmt, "bind_result"), $ b_res) Где $ result - количество столбцов, возвращаемых после выполнения. Затем, когда я это делаю, while ($ stmt-> fetch()) {array_push ($ r_val, $ b_res);} все, что я получаю, это последняя строка из набора результатов. Это происходит из-за проблемы, которую я опубликовал. Есть ли способ, который я могу только скопировать значение в новую переменную, а затем вернуть его? – maurya8888

ответ

-1

Все они относятся к одному объекту массива в памяти

+0

Если все они относятся к одному и тому же объекту, то почему var_dump ($ b) дает «три», он должен давать «два», поскольку я изменил значение $ a на «two» – maurya8888

3

Ваша проблема:

$b[0] = &$a[0]; 

Это ссылается на первый элемент массива. Как видно на выходе var_dump()&string(5).

Так $b не ссылается на весь массив, только на первый элемент.

Для ссылки на весь массив, вам нужно сделать:

$b = &$a; 

Это работает, как вы ожидаете:

// $a 
array(1) { 
    [0]=> 
    string(3) "two" 
} 
// $b 
array(1) { 
    [0]=> 
    string(3) "two" 
} 
// $c 
array(1) { 
    [0]=> 
    string(3) "one" 
} 

Подробнее о Arrays in PHP.

2

Это шаг за шагом объяснение:

$a = array('one'); 
$b[0] = &$a[0]; 

$b теперь массив и его первый элемент ссылается на первый элемент $a. В таблице символов $b[0] и $a[0] указывают на тот же базовый zval.

$c = $a; 

$c ссылки $a сейчас, но копия не была сделана (копия семантики записи). Это выглядит очень похоже на это:

$c ----/----> $a    $b 
(0: 'one') 0: 'one' <---- 0: 'one' 

Следующее утверждение:

$b[0] = 'three'; 

Это обновляет $a[0], а также, и в свою очередь обновления $c[0], потому что $a сама не меняется. Теперь это выглядит;

$c ----/----> $a    $b 
(0: 'three') 0: 'three' <---- 0: 'three' 

Следующее заявление:

$a = array('two'); 

Отсоедините $a от $c и $a[0] от $b[0].

$c   $a  $b 
0: 'three' 0: 'two' 0: 'three' 

Профилактика

Чтобы предотвратить такое поведение, вы должны ссылаться на весь массив, а не только одного элемента:

$b = &$a; 

Делая это, $b и $a Теперь ссылки на то же самое zval (сам массив), поэтому любые сделанные изменения отключат его от $c.

Я бы рассмотрел эти краевые случаи языка, хотя я бы советовал не использовать ссылки, если вам это не нужно.

+0

Я не понимаю, почему $ c = $ a не копирует значение, но вместо этого создает ссылку. Есть ли что-то, что я могу сделать здесь, чтобы это не было ссылкой? По-видимому, это единственное, что я могу изменить в коде. – maurya8888

+1

@ maurya8888 Я обновил ответ, как это можно предотвратить. Конечно, если бы вы вообще не использовали ссылки, у вас никогда не было бы этой проблемы :) –

+0

@Jack, я думаю, они исходят из C, как они ссылаются на массив. –

1

Важно понимать, что вы делаете, назначая по ссылке или значению. Пойдем по очереди.

$a = array('one'); 

Место расположения памяти, мы назовем его M1. $ a указывает на M1 и внутри M1 мы имеем массив с 1 входом, назовем его M1-A1.

$b[0] = &$a[0]; 

Теперь то, что мы делаем, указывает на $ b [0] на M1-A1. Помните, что $ a [0] также указывает на M1-A1, поэтому оба указывают на эту конкретную часть памяти. Помните, что в самом $ b есть собственное место памяти, M2, но внутри M2 мы указываем M1-A1 (т. Е. M2-A1 указывает на M1-A1).

$c = $a; 

Поскольку мы не назначая по ссылке, что мы получаем новое место в памяти, давайте назовем его M3, но в пределах М3 есть массив с первым элементом все еще указывает на M1-A1.

Итак, теперь у нас есть M1, M2, M3 с массивом в M2 и M3, указывающим на M1-A1.

$b[0] = 'three'; 

С $ Ь [0] на самом деле указывает на M1-A1, мы на самом деле изменения значения пятне памяти M1-A1. Таким образом, все, что указывает на место M1-A1, также увидит изменение этого значения.

$a = array('two'); 

Мы полностью меняем местоположение памяти для $ a на этом этапе. Первоначально это был M1, теперь мы создаем новую ячейку памяти, M4. Ничто другое не указывает на M4 и M4-A1 НЕ указывает на M1-A1.

Итак, когда мы делаем дамп var, мы получаем значения, которые вы упомянули.

Я, вероятно, сделал это более запутанным, но попробуйте нарисовать его на бумаге, и это будет довольно ясно. Поймите, что все хранится в памяти, а переменные просто указывают на места в памяти. Как только вы поймете этот принцип, все встанет на свои места.

+0

Отлично! Теперь я могу сделать что-то, чтобы M3 не указывал на M1-A1, а просто сохранял значение в M1-A1. Например, если бы это был C, я бы использовал * перед $ a – maurya8888

+0

. Один маленький тик, который я видел, должен передать массив функции. PHP автоматически удалит ссылку и установит ее как значение. Итак, если мы сделали $ c = $ a; $ c = array_flip (array_flip ($ c)); то у нас было бы все в $ a как значения и больше никаких ссылок. (Вам не нужно использовать array_flip, это просто пример) – SaidK

+0

Да, что-то вроде $ c = json_decode (json_encode ($ a)) сделал трюк. – maurya8888

Смежные вопросы