2010-02-05 12 views
5

मेरे पास एक कण प्रणाली में वसंत नामक एक वर्ग है। निर्माता की तरह दिखता है:2 डी वेक्टर (सी ++) में तत्व के संदर्भ

Spring(Particle& _a, Particle& _b); 

और मैं कण का एक वेक्टर है और मैं

Spring mySpring = Spring(myParticles.at(j),myParticles.at(j+1)); 

का उपयोग एक पाश के अंदर दो कणों के बीच एक वसंत बल जोड़ने के लिए। सब कुछ ठीक काम करता है। हालांकि, मैं कणों के 2 डी वेक्टर का उपयोग करना चाहता हूं। यह है:

Spring mySpring = Spring(myParticles.at(i).at(j),myParticles.at(i).at(j+1)); 

और मुझे कण का संदर्भ नहीं मिलता है। पहले उदाहरण में, जब भी मैं अपने वसंत वर्ग में कण बदलता हूं, वेक्टर में कण बदल जाता है। दूसरे उदाहरण में परिवर्तन केवल स्थानीय रूप से हैं। मैं 2 डी वेक्टर में कण कैसे बदल सकता हूं?

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

मैं कुछ कण प्रणाली है और उनमें से प्रत्येक कण के एक नंबर के होते हैं: मैं स्पष्ट कुछ चीजें बनाने के लिए प्रयास करें। प्रत्येक कण केवल उन अन्य कणों के साथ बातचीत करनी चाहिए जो स्वयं के समान सिस्टम में हैं। इसलिए मेरे पास कण प्रणालियों का वेक्टर होता है जिसमें प्रत्येक कण sytem कण वस्तुओं के वेक्टर होते हैं। (यह 2 डी वेक्टर बनाता है)। पहला आयाम (i) प्रणाली है, दूसरा (जे) व्यक्तिगत कण। सिस्टम में कण एक दूसरे के साथ बातचीत करते हैं (टक्कर, टालना, जो भी ..) और उनकी स्थिति बदल जाती है। और वेक्टर "अद्यतन" हो जाता है। (यानी, संदर्भ काम करता है)।

हालांकि, मेरे पास वसंत बलों का दूसरा (1 डी) वेक्टर है। वसंत बल भी कणों की स्थिति को अद्यतन करने के लिए प्रयोग किया जाता है। मेरे निर्माता निम्नलिखित है:

Spring::Spring(Particle& _a, Particle& _b) { 
    a=&_a; 
    b=&_b; } 
एक साथ

और ख कण जा रहा है *। इसलिए मैं 2 डी वेक्टर में पॉइंटर्स को दो कणों में स्टोर करता हूं। एक और समारोह Spring.doSpring() कणों की स्थिति में परिवर्तन करता है।

a->pos.x=300; 

या

a->velocity+=something.. 

पहला उदाहरण मैं पोस्ट मैं केवल एक कण प्रणाली का इस्तेमाल किया है और इसलिए एक 2d सदिश की कोई जरूरत नहीं थी। और सब कुछ ठीक काम करता है। वेक्टर में कण अद्यतन हो जाता है। लेकिन दूसरे उदाहरण के साथ मेरा प्रोग्राम चलता है लेकिन किसी भी तरह से कोई फर्क नहीं पड़ता कि डूस्पिंग फ़ंक्शन क्या करता है, 2 डी वेक्टर में कण अद्यतन नहीं होते हैं।

+0

आप "myParticles" कैसे घोषित कर रहे हैं? – coelhudo

+0

हे, http://www.drdobbs.com/cpp/184401863 से एक टिप: "नामकरण को ओवरलैस्लेट न करें, लेकिन एक सतत नामकरण सम्मेलन का उपयोग करें: केवल दो आवश्यक हैं: ए) कभी भी" अंडरहाइड नामों का उपयोग न करें , "वे जो अंडरस्कोर से शुरू होते हैं या जिनमें डबल अंडरस्कोर होता है;" हर्ब सटर और आंद्रेई अलेक्जेंड्रेस्कू के शब्द – coelhudo

उत्तर

0

यदि मैं सही ढंग से समझता हूं तो आप std::vector का उपयोग करके कणों की 2 डी सरणी बनाना चाहते हैं?

यदि ऐसा है तो आप इसे std::vector<std::vector<Particle> > के रूप में घोषित कर सकते हैं। इसके बाद आप तत्वों तक पहुंचने के लिए [][] नामकरण का भी उपयोग कर सकते हैं। (खतरे विल रॉबिन्सन! कोई सीमा इस ऑपरेटर का उपयोग करते समय की जाँच)

लेकिन अगर यह 2 डी सरणी ज्यादातर शून्य तो शामिल होंगे यह कुंजी के रूप में सूचकांक के साथ एक map उपयोग करने के लिए ठीक हो सकता है।

+0

उनके कोड ('.at (i) .at (j)') के आधार पर निर्णय लेते हुए, वह पहले से ही वैक्टरों का वेक्टर उपयोग कर रहा है। –

+0

उपर्युक्त उदाहरणों के आधार पर, ऐसा लगता है कि वह पहले से ही क्या करने की कोशिश कर रहा है ("at (...)। (...)" भाग)। – rjnilsson

1

मुझे लगता है कि सी ++ एफएक्यू से this series लाइट मदद करनी चाहिए।

कृपया "ऑपरेटर ओवरलोडिंग" हेडर द्वारा भ्रमित न हों।आपको निश्चित रूप से वहां से 13.10, 13.11 और 13.12 पढ़ना चाहिए।

5

क्या आप दिखता है ठीक कर रहे हैं - निम्नलिखित कोड एक "2 डी" वेक्टर बनाता है और दिखाता है कि .at()() पर निर्माण आप एक संदर्भ देता है:

#include <vector> 
#include <iostream> 
using namespace std; 

int main() { 
    vector <vector<int> > vi; 
    vi.push_back(vector <int>()); 
    vi.at(0).push_back(42); 
    cout << vi.at(0).at(0) << endl; // prints 42 
    vi.at(0).at(0) = 666; 
    cout << vi.at(0).at(0) << endl; // prints 666 
} 
6

सबसे में से एक। वेक्टर के अंदर तत्वों के संदर्भ/पॉइंटर्स लेने वाले सामान्य मुद्दे पुनर्वितरण हैं। यदि आप push_back, उदाहरण के लिए, यह संभव है कि वेक्टर अपनी क्षमता से अधिक हो जाए, स्मृति का एक नया ब्लॉक आवंटित करें, सब कुछ कॉपी करें, फिर पुराने ब्लॉक को मुक्त करें। यदि आपने वेक्टर के अंदर तत्वों के संदर्भ या पॉइंटर्स ले लिए हैं, तो ये अभी भी पुराने ब्लॉक को इंगित करते हैं, अब मृत स्मृति, और एक गंभीर बग है!

तो मैं अनुमान लगा रहा हूं कि आपके कण प्रभाव आपके कणों के वेक्टर में नए कण जोड़ते रहते हैं, जो किसी बिंदु पर वेक्टर को क्षमता से अधिक होने पर पुन: आवंटित करने का कारण बनता है। वसंत वर्ग द्वारा संग्रहीत पॉइंटर्स को अद्यतन नहीं किया जाता है, इसलिए मृत स्मृति को इंगित करें और वास्तविक कण पर कोई प्रभाव नहीं पड़ता है, जो वेक्टर द्वारा कहीं और स्थानांतरित हो गया है।

वेक्टर के अंदर किसी तत्व को संदर्भ या पॉइंटर न लें। पॉइंटर्स, एक सूची, या कुछ अन्य कंटेनर का वेक्टर का उपयोग करें जो वास्तविक तत्वों के स्मृति पते के चारों ओर घूमने वाला नहीं है। यदि आपको, वेक्टर के अंदर तत्वों के लिए इटरेटर का उपयोग करना है। डिबग बिल्ड में, यह मानते हुए कि आपको एक एसटीएल कार्यान्वयन मिला है, यदि आप वेक्टर पुन: आवंटित होने के बाद इटरेटर के माध्यम से तत्व तक पहुंचते हैं तो आपको डीबग अलर्ट मिल जाएगा।

+1

लेकिन क्या ऐसा नल पॉइंटर्स नहीं होगा जिससे एप्लिकेशन क्रैश हो जाएगा? चूंकि मेरा एप्लिकेशन क्रैश नहीं होता है, इसलिए तत्व अपडेट नहीं होते हैं। हालांकि, यह एक अच्छा जवाब है, मैंने पुनर्वितरण के बारे में नहीं सोचा था। – hrst

+0

नहीं, कुछ शून्य सूचक पर सेट नहीं हो जाता है: वेक्टर स्प्रिंग क्लास में पॉइंटर्स के बारे में नहीं जानता है, इसलिए उन्हें कभी भी बदलने का कोई प्रयास नहीं करता है। पॉइंटर्स * संशोधित या शून्य नहीं हैं, वे सिर्फ एक मृत स्मृति स्थान को इंगित करते हैं। चूंकि स्मृति शायद आपकी प्रक्रिया के अंदर कहीं भी है, इसलिए इस तथ्य के बावजूद कि आप शायद अपने एप्लिकेशन की स्मृति को दूषित कर रहे हैं, पढ़ और लिखने की अनुमति है। – AshleysBrain

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