2012-05-15 14 views
13

मेरे पास एक सरणी है जिसका उपयोग मैं एक पेड़ के माध्यम से पथ को स्टोर करने के लिए एक ढेर के रूप में उपयोग कर रहा हूं। प्रत्येक तत्व पेड़ में एक नोड को इंगित करता है और मैं अंतिम तत्व को बंद करना चाहता हूं और उसके बाद उस तत्व द्वारा संदर्भित ऑब्जेक्ट को शून्य पर सेट करना चाहता हूं।क्या PHP में संदर्भ को हटाना संभव है?

मूल रूप से

:

$node = array_pop($path); 
*$node = null; 

यह सोचते हैं कि पीएचपी से '*' के रूप में सी-ish भाषाओं करना ऑपरेटर था। अभी मैं माता पिता के नोड और याद जो बच्चे मैं ले लिया पर शुरू और फिर में अशक्त करने के लिए है कि सेटिंग के रूप में की बदसूरत समाधान है:

if($goLeft) { 
    $parent->left = null; 
} else { 
    $parent->right = null; 
} 

मैं कहता हूँ यह बदसूरत है क्योंकि पथ युक्त सरणी एक द्वारा बनाई गई है मेरे पेड़ वर्ग में सार्वजनिक समारोह। मैं PHP में एक idiosyncrasy (सुविधा?) को संबोधित करने वाले कार्यान्वयन विवरण को उजागर किए बिना पेड़ के माध्यम से सीधे रास्ते में नोड्स पर काम करने की क्षमता का खुलासा करना चाहता हूं। एटीएम मुझे वापसी मूल्य में एक बूलियन शामिल करने की आवश्यकता है (इस मामले में $ goLeft) बस मैं संदर्भ को अस्वीकार करने में असमर्थता का काम कर सकता हूं।

यह दूसरी बार है जब मुझे इस समस्या का सामना करना पड़ा, इसलिए यदि कोई तरीका जानता है तो मैं कोड के पहले ब्लॉक के समान कुछ कर सकता हूं कृपया साझा करें!

(संपादित)

& की और सरणियों के कई क्रमपरिवर्तन के साथ प्रयोग करने के बाद, यह पता चला है कि बुनियादी समस्या यह है कि मैं एक त्रुटि मैं हो रही थी के लिए कारण गलत व्याख्या की थी।

मैं

$a = ($x > $y) ? &$foo[$bar] : $blah; 

की कोशिश की और "सिंटैक्स त्रुटि, अप्रत्याशित '&'" मिला है। मैंने इसका अर्थ यह बताया कि समस्या - $foo[$bar] पर ऑपरेटर का उपयोग कर रही थी। यह वास्तव में पता चला है कि दोषी है? -operator,

if($x > $y) { 
    $a = &$foo[$bar]; 
} else { 
    $a = null; 
} 

काम करता है बिल्कुल ठीक है। इस प्रकार मैं एक जंगली हंस पीछा चला गया जो किसी समस्या के लिए कामकाज की तलाश में था जो अस्तित्व में नहीं था। जब तक मैं & की श्रृंखला को तोड़ता नहीं हूं, तो PHP मैं जो चाहता हूं वह करता है, जो किसी चर द्वारा संदर्भित ऑब्जेक्ट पर संचालित होता है (चर स्वयं नहीं)। उदाहरण

$a1 = new SomeClass; 
$a2 = &$a1; 
$a3 = &$a2; 
$a4 = &$a3; 

$a4 = 42; // This actually sets $a1 to 42 
var_dump($a1); // Emits 42 

मुझे क्या गड़बड़ ऊपर है कि मैंने सोचा था कि वस्तुओं संदर्भ द्वारा आसपास पारित कर रहे हैं वैसे भी (यह गलत है), इसलिए मुझे नहीं लगता था & जरूरी हो गया था अगर अभिव्यक्ति एक वस्तु का संकल्प लिया है। मेरा मतलब है:

class A { 
    public $b; 
} 

class B {} 

$a = new A; 
$a->b = new B; 

$c1 = $a->b; 
$c2 = &$a->b; 

$c1 = 42; // Merely assigns 42 to $c1 
$c2 = 42; // Assigns 42 to $a->b 

ऐसा लगता है कि इस सटीक मुद्दा http://www.php.net/manual/en/language.oop5.references.php में संबोधित किया जाता है। इच्छा है कि पहली बार मैंने इसे पढ़ा था!

+1

मुझे यकीन नहीं है, यह वही है जो आप चाहते हैं, लेकिन आप 'unset ($ parent-> left) का उपयोग कर सकते हैं;' 'parent-> left = null;' – Leri

+4

@PLB: मुझे लगता है कि आपका मतलब है ' अनसेट ',' अनलिंक 'नहीं। –

+1

@ रॉकेट निश्चित रूप से, मैं करता हूं। बहुत थक गई हूं। – Leri

उत्तर

7

बहुत ही रोचक सवाल! मुझे एक वर्कअराउंड मिल सकता है: यदि आप & ऑपरेटर के साथ ऑब्जेक्ट संदर्भों के साथ सरणी को पॉप्युलेट करते हैं, तो आप उस ऑब्जेक्ट मान को NULL पर सेट करके मूल ऑब्जेक्ट को नष्ट कर सकते हैं। array_pop द्वारा लौटाए गए चर का उपयोग करने के बजाय, आपको सरणी पर सीधे संचालन करना होगा। उसके बाद आप उस स्थिति को मुक्त करने के लिए सरणी को पॉप कर सकते हैं (जिसमें उसके बाद NULL मान होगा)।

यह वह जगह है मैं क्या मतलब है (रॉकेट के कोड के आधार पर):

php में
$a=(object)'a'; 
$b=array(&$a); 
$b[0] = NULL; 
// array still contains an element 
array_pop($b); 
// now array is empty 
var_dump($a); // NULL 

http://codepad.org/3D7Lphde

+0

वाह, साफ। वह वास्तव में काम करता है! –

+0

@bfavaretto: आपने इसे हल किया! बहुत बढ़िया, और इतना आसान! मैं कहता हूं कि जो कुछ मैं चाहता था उसे करने का एक शानदार तरीका है। सभी मदद लोगों के लिए धन्यवाद, ढेर ओवरफ्लो नियम! – kahulio

+0

हे - यह लगभग उतना आसान था जितना मैंने सोचा था कि यह होना चाहिए ... पता था कि कोई घर आने से पहले वहां पहुंच जाएगा: डी चाल सरणी में संदर्भों का उपयोग कर रही है। – CD001

0

बस array_pop() वापसी मूल्य असाइन न करें।

php > $test = array(1, 2, 3); 
php > $test2 = array(0 => &$test[0], 1 => &$test[1], 2 => &$test[2]); 
php > array_pop($test2); 
php > var_dump($test); 
array(3) { 
    [0]=> 
    &int(1) 
    [1]=> 
    &int(2) 
    [2]=> 
    int(3) 
} 
php > var_dump($test2); 
array(2) { 
    [0]=> 
    &int(1) 
    [1]=> 
    &int(2) 
} 
+0

काफी नहीं। वह जो चाहता है वह "मूल" ऑब्जेक्ट को अनसेट करने के लिए है ('$ test [2]')। 'Array_pop' का वापसी मूल्य क्यों मायने रखता है? आप किसी भी तरह से '$ test2' को संशोधित कर रहे हैं। –

+0

अच्छा ... विवरण से प्राप्त करना मुश्किल है। :) – Narf

1

मेरी इच्छा है कि मुझे याद आए कि मैं इसे कहां पढ़ूं, लेकिन PHP किसी दिए गए ऑब्जेक्ट के संदर्भों का काउंटर बनाए रखकर काम करता है। आपके पास कुछ ऑब्जेक्ट है (उदा। Tree) जिसमें कुछ नोड्स का संदर्भ है। जब आप array_pop का उपयोग करते हैं, तो नोड ऑब्जेक्ट का संदर्भ लौटाया जाता है (यानी एक अतिरिक्त संदर्भ बनाया गया है), लेकिन मूल संदर्भ अभी भी मौजूद है।जब आप unset पॉप किए गए संदर्भ को नष्ट कर देते हैं, लेकिन मूल वस्तु नष्ट नहीं होती है क्योंकि Tree अभी भी उस संदर्भ में है। उस ऑब्जेक्ट की स्मृति को मुक्त करने का एकमात्र तरीका Tree व्यक्तिगत रूप से इसे नष्ट करना है (ऐसा लगता है कि आप दूसरे कोड ब्लॉक में क्या कर रहे हैं)।

PHP में मेमोरी डेलोकेशन या कचरा संग्रहण को मजबूर करने के लिए कोई विधि प्रतीत नहीं होती है, इसलिए जब तक कि आप सावधानीपूर्वक अपने संदर्भों को संभाल नहीं लेते, तो आप अटक जाते हैं।

यह संभव नहीं है

पी.एस. मैं अभी भी वास्तव में उलझन में हूं कि आप क्या करने की कोशिश कर रहे हैं। रॉकेट की व्याख्या मदद करता है, लेकिन $path क्या है, और यह दूसरे ब्लॉक से कैसे संबंधित है?

+0

मुझे लगता है कि मेरा मूल प्रश्न अत्यधिक विशिष्ट था। यह वास्तव में कोई फर्क नहीं पड़ता कि मैं एक ढेर के साथ काम कर रहा हूं, या कुछ शून्य सेट करने की कोशिश कर रहा हूं। मुझे खुद को समझाने में बेहतर होना चाहिए। मान लें कि मेरे पास एक वेरिएबल है जो किसी चीज़ का संदर्भ रखता है - एक वस्तु, एक अन्य चर, इससे कोई फर्क नहीं पड़ता। उदाहरण: '$ a = &$b;' अब मैं '$ a' द्वारा निर्दिष्ट चीज़ पर एक ऑपरेशन करना चाहता हूं, जो इस मामले में' $ b' है। हो सकता है कि मैं '$ b' को शून्य, स्ट्रिंग" एलिस "या किसी अन्य ऑब्जेक्ट पर सेट करना चाहता हूं। कोई फर्क नहीं पड़ता। वैसे भी, यह वही है जो मैं पूरा करने की कोशिश कर रहा हूं। – kahulio

+0

@kahulio यह समझाने के लिए थोड़ा मुश्किल है। असल में, '$ ए = और $ बी'' $ a' से '$ b' तक एक प्रतीक तालिका उपनाम बनाता है। यही है, जो कुछ भी आप '$ ए' से करते हैं, वह सीधे '$ बी' को प्रभावित करता है। यदि '$ b' कोई ऑब्जेक्ट है, तो' $ a = $ b' ऑब्जेक्ट संदर्भ को '$ b' से' $ a' तक कॉपी करता है। ऑब्जेक्ट '$ a' पर ऑपरेशंस का ऑब्जेक्ट '$ b' जैसा ही प्रभाव होता है, लेकिन यह एक अलग प्रतीक तालिका प्रविष्टि है। यदि आप '$ a' (' $ a = 'blah'; ') पर लिखते हैं तो यह '$ b' को बिल्कुल प्रभावित नहीं करता है। 'array_pop' * संदर्भ नहीं देता है (उपनाम) और नहीं कर सकता है, इसलिए इसके वापसी मूल्य पर लिखना मूल वस्तु को किसी भी तरह से प्रभावित नहीं करता है, न ही यह कर सकता है। –

0
$one = 1; 
$two = 2; 
$array = array(&$one, &$two); 

// magic 
end($array); 
$array[key($array)] = NULL; 

var_dump($two); 
// NULL 

संदर्भ आप वस्तु को बदलने के लिए अनुमति देता है।

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