2014-09-28 5 views
17

मैं दूसरे दिन How to changing value in $array2 without referring $array1? पर इस प्रतीत होता है कि यह बहुत ही सरल सवाल आया है, लेकिन जितना अधिक मैंने देखा उतना ही यह अजीब लग रहा था कि यह वास्तव में इरादे से काम कर रहा है। इसके बाद मैंने निम्नलिखित के आउटपुट से उत्पन्न ओपोड्स को देखना शुरू कर दिया।संदर्भ बग द्वारा असाइन करें

$array1 = array(2, 10); 
$x = &$array1[1]; 
$array2 = $array1; 
$array2[1] = 22; 

echo $array1[1]; // Outputs 22 

यह मेरे लिए पागल के बाद से array2 केवल array1 और कुछ भी है कि एक सरणी के लिए होता अन्य की सामग्री को प्रभावित नहीं करना चाहिए की एक प्रति होना चाहिए लगता है। बेशक यदि आप दूसरी पंक्ति पर टिप्पणी करते हैं तो अंतिम पंक्ति उम्मीद की तरह 10 को प्रतिबिंबित करेगी।

आगे देखकर मैं एक अच्छी साइट देख सकता हूं जो मुझे ओपोडोड दिखाता है जो PHP Vulcan Logic Dumper का उपयोग करता है। उपर्युक्त कोड द्वारा उत्पन्न ओपोडोड यहां दिए गए हैं।

Finding entry points 
Branch analysis from position: 0 
Return found 
filename:  /in/qO86H 
function name: (null) 
number of ops: 11 
compiled vars: !0 = $array1, !1 = $x, !2 = $array2 
line  # * op       fetch   ext return operands 
--------------------------------------------------------------------------------- 
    3  0 > INIT_ARRAY          ~0  2 
     1  ADD_ARRAY_ELEMENT        ~0  10 
     2  ASSIGN             !0, ~0 
    4  3  FETCH_DIM_W          $2  !0, 1 
     4  ASSIGN_REF            !1, $2 
    5  5  ASSIGN             !2, !0 
    6  6  ASSIGN_DIM            !2, 1 
     7  OP_DATA             22, $6 
    8  8  FETCH_DIM_R          $7  !0, 1 
     9  ECHO              $7 
     10 > RETURN             1 

ये opcodes यहाँ महान http://php.net/manual/en/internals2.opcodes.php दस्तावेज नहीं कर रहे हैं, लेकिन मैं अंग्रेजी में विश्वास करते हैं opcodes निम्नलिखित कर रहे हैं। लाइन से ... किसी और की तुलना में मेरे लिए अधिक हो सकता है।

  1. रेखा 3: हम सरणी को इसके पहले मान के साथ प्रारंभ करते हैं और फिर इसे $ array1 को सौंपने से पहले इसमें 10 जोड़ते हैं।
  2. रेखा 4: केवल एक लेख प्राप्त करें? सरणी से मूल्य और इसे $ x के संदर्भ में असाइन करें।
  3. रेखा 5: $ array1 से $ array2 सेट करें।
  4. रेखा 6: 1. od_data की सरणी अनुक्रमणिका प्राप्त करें मैं अनुमान लगा रहा हूं कि इसे 22 पर सेट किया गया है हालांकि $ 6 कभी वापस नहीं आया है। OD_DATA में बिल्कुल कोई प्रलेखन नहीं है और मैंने देखा है कि कहीं भी एक ओपोड के रूप में सूचीबद्ध नहीं है।
  5. रेखा 8: $ 1 के 1 सूचकांक से केवल पढ़ने योग्य मान प्राप्त करें और इसे प्रतिबिंबित करें।

ओपकोड्स के माध्यम से भी काम करना मुझे यकीन नहीं है कि यह गलत कहां जा रहा है। मुझे ऑपकोड पर दस्तावेज़ीकरण की कमी महसूस हो रही है और उनके साथ काम करने में मेरी अनुभवहीनता मुझे यह पता लगाने से रोक रही है कि यह कहां गलत हो रहा है।

संपादित करें 1:

के रूप में पहली टिप्पणी सरणियों में माइक से कहा संदर्भ जब वे कॉपी कर रहे हैं स्थिति संरक्षित है। यहां http://php.net/manual/en/language.types.array.php#104064 से लिंक किए गए सरणी आलेख में किसी स्थान के साथ प्रलेखन देखा जा सकता है। यह मजाकिया पर्याप्त चेतावनी नहीं माना जाता है। मेरे लिए आश्चर्य की बात यह है कि यदि यह सच है तो संदर्भ कोड इस कोड के लिए संरक्षित नहीं है जैसा आप उम्मीद करेंगे।

$array1 = array(2, 10); 
$x = &$array1; 
$array2 = $array1; 
$array2[1] = 22; 

echo $array1[1]; // Output is 10 

तो ऐसा लगता है कि यह केवल होता है जब आप कोशिश करते हैं और इस कार्यक्षमता भी अधिक भ्रमित कर रही है संदर्भ द्वारा एकल तत्वों आवंटित।

PHP केवल व्यक्तिगत रूप से असाइन किए जाने पर सरणी अनुक्रमणिका की स्थिति को संरक्षित क्यों करता है?

संपादित करें 2:

मैं कुछ आज HHVM का उपयोग कर परीक्षण किया था और HHVM कोड के पहले स्निप-यह संभालती है आप कैसे लगता है कि यह होगा। मुझे PHP पसंद है लेकिन एचएचवीएम ज़ेंड इंजन पर बेहतर और बेहतर दिख रहा है।

+4

क्यों http://php.net/manual/en/language.types.array.php#104064 देखें। "साझा" डेटा साझा रहता है। –

+2

यह मेरे लिए पागल लगता है क्योंकि आप वास्तव में सरणी संरचना को बदल रहे हैं जब आप संदर्भ के इसके हिस्सों को संदर्भित करते हैं। इसके अलावा यदि आप लाइन 2 से [1] को हटाते हैं तो डेटा साझा डेटा समान नहीं रहता है, इसलिए यह पूरी तरह से सत्य नहीं है। – mschuett

+1

आरंभिक असाइनमेंट सिर्फ एक उपनाम है। एक बार जब आप उन्हें स्वतंत्र संचालन के साथ छेड़छाड़ करना शुरू नहीं करते हैं जैसे '... []' कि उन्हें अलग करने के लिए मजबूर किया जाता है। यह निश्चित रूप से "अप्रत्याशित" है, लेकिन मैं इसे "पागल" कहने के लिए अब तक नहीं जाऊंगा। हालांकि मैं इस बात की खुशी से खुश हूं कि इसे बनाया जाने पर बहुत अच्छा विकल्प नहीं था, और तब से PHP इसके साथ फंस गया है। –

उत्तर

10

यह, विशेष रूप से अधिक http://php.net/manual/en/language.types.array.php#104064

"साझा" डेटा पर पीएचपी पुस्तिका (आप अधिक समय बिताने की तुलना में आप यह खोजने के लिए करने के लिए होना चाहिए है, भले ही) पर अधिक से समझाया गया है के साथ साझा रहता है, शुरुआती असाइनमेंट सिर्फ उपनाम के रूप में कार्य करता है। यह तब तक नहीं है जब तक आप ...[] = ... जैसे स्वतंत्र संचालन के साथ सरणी में हेरफेर करना शुरू नहीं करते हैं कि इंटिप्टर उन्हें अलग-अलग सूचियों के रूप में व्यवहार करना शुरू कर देता है, और फिर भी साझा डेटा साझा रहता है ताकि आपके पास साझा किए गए पहले n तत्वों के साथ दो सरणी हो सकें लेकिन बाद के डेटा अलग हो जाएं ।

एक सच्चे एक से दूसरे सरणी के लिए "मूल्य से नकल" के लिए, आप काफी

$arr2 = array(); 
foreach($arr1 as $val) { 
    $arr2[] = $val; 
} 

या

$arr2 = array(); 
for($i=count($arr1)-1; $i>-1; $i--) { 
    $arr2[$i] = $arr[$i]; 
} 

की तरह कुछ कर रही अंत (का उपयोग कर पाशन रिवर्स ज्यादातर क्योंकि पर्याप्त नहीं लोग याद रखें कि यह एक चीज है जो आप कर सकते हैं, और आगे लूप की तुलना में अधिक कुशल है =)

आप कल्पना करेंगे कि array_copy फ़ंक्शन या मदद करने के लिए कुछ होगा सरणी प्रतिलिपि quirk के साथ सौदा, लेकिन वहाँ एक प्रतीत नहीं होता है। यह अजीब है, लेकिन उनमें से एक "PHP राज्य" चीजों में से एक है। अतीत में एक विकल्प बनाया गया था, पीपीपी परिणाम के साथ कुछ ही वर्षों के लिए उस विकल्प के साथ रहता था, इसलिए यह सिर्फ "उन चीजों में से एक" है। दुर्भाग्य!

+0

इसके लिए धन्यवाद ... यह मुद्दा मुझे भी परेशान कर रहा था (क्योंकि सप्ताह में पहले मूल पोस्टिंग देख रहा था)। मैं PHP के साथ एक वास्तविक नौसिखिया हूं जो इतनी धीमी गति से धीमा है, इसलिए मैंने अपने ब्लॉग पर थोड़ा और देखा: http://blog.adamcameron.me/2014/09/php-looking-at-some-interesting.html । क्या मुझे यहां अपने विश्लेषण में छड़ी का सही अंत मिलता है? –

+0

यह एक अच्छा लेखन और मेरे बारे में सही लगता है। इसे ज़ेंड और php_net पर ट्वीट करें और देखें कि क्या इसे रीट्वीट के माध्यम से कुछ कर्षण मिलता है =) –

+0

@AdamCameron मैंने उन पर आपकी पोस्ट को ट्वीट किया ताकि यह देखने के लिए कि हम इस पर कुछ आंदोलन प्राप्त कर सकते हैं या नहीं। मुझे लगता है कि यह PHP 7 के लिए एक शानदार बदलाव होगा। – mschuett

संबंधित मुद्दे