C ++ के साथ कोडिंग करते समय पॉइंटर्स की सिफारिश क्यों नहीं की जाती है?


45

मैंने कहीं से पढ़ा है कि C ++ का उपयोग करते समय यह इंगित किया जाता है कि पॉइंटर्स का उपयोग न करें। जब आप C ++ का उपयोग कर रहे हैं तो पॉइंटर्स ऐसा बुरा विचार क्यों है। C प्रोग्रामर्स के लिए जिनका उपयोग पॉइंटर्स का उपयोग करने के लिए किया जाता है, C ++ में बेहतर विकल्प और दृष्टिकोण क्या है?


40
कृपया "कहीं" से लिंक करें। संदर्भ बहुत प्रासंगिक हो सकता है।

1
यह प्रश्न आपके लिए उम्मीद से उपयोगी है।
गार्ट क्लैबोर्न

इनमें से अधिकांश उत्तर प्राथमिक कारण के रूप में मेमोरी लीक से बचने का उल्लेख करते हैं। मुझे याद नहीं है कि पिछली बार हमारे किसी ऐप में पॉइंटर्स का उपयोग करने के बावजूद मेमोरी लीक की समस्या थी। यदि आपके पास मेमोरी लीक की समस्या है तो आप सही टूल का उपयोग नहीं कर रहे हैं या आप नहीं जानते कि आप क्या कर रहे हैं। अधिकांश विकास परिवेशों में स्वचालित रूप से निर्मित लीक्स की जांच करने का एक तरीका है। मुझे लगता है कि मेमोरी लीक के मुद्दे कचरा एकत्र भाषाओं में नीचे ट्रैक करना अधिक कठिन है क्योंकि उनकी घटना कहीं अधिक सूक्ष्म है और आपको अपराधी को ट्रैक करने के लिए अक्सर एक 3 पार्टी टूल की आवश्यकता होती है। ।
डंक

1
@ डंक की टिप्पणी में जोड़ना, कभी-कभी उच्च-स्तरीय भाषाओं में निर्मित कचरा संग्रहकर्ता केवल सही काम नहीं करते हैं। उदाहरण के लिए ActionScript 3 का कचरा संग्रहकर्ता नहीं है। अभी इसमें एक बग है NetConnectionजिसे सर्वर से डिस्कनेक्ट करने के उदाहरणों के साथ करना है ( stackoverflow.com/questions/14780456/… ), और साथ ही एक प्रोग्राम में कई ऑब्जेक्ट्स होने के साथ एक मुद्दा है कि यह विशेष रूप से कभी इकट्ठा करने के लिए मना कर देगा ...
पैंजरक्रिस 13

... ( adobe.com/devnet/actionscript/learning/as3-fundamentals/… - खोजें GCRoots are never garbage collected.और इसके द्वारा शुरू किया गया पैराग्राफ The MMgc is considered a conservative collector for mark/sweep.)। तकनीकी रूप से यह Adobe वर्चुअल मशीन 2 में एक समस्या है, AS3 में ही नहीं, लेकिन जब आपको उच्च-स्तरीय भाषाओं में इस तरह की समस्याएँ होती हैं, जिनका कचरा संग्रह अनिवार्य रूप से निर्मित होता है, तो आपके पास अक्सर भाषा को डीबग करने का कोई सही तरीका नहीं होता है ये मुद्दे पूरी तरह से कार्यक्रम से बाहर हैं। ...
पैंजरक्रिस 13

जवाबों:


58

मुझे लगता है कि उनका मतलब है कि आपको नियमित पॉइंटर्स के बजाय स्मार्ट पॉइंटर्स का उपयोग करना चाहिए ।

कंप्यूटर विज्ञान में, एक स्मार्ट पॉइंटर एक अमूर्त डेटा प्रकार है जो अतिरिक्त सुविधाओं को प्रदान करते समय एक पॉइंटर का अनुकरण करता है, जैसे कि स्वचालित कचरा संग्रह या सीमा जाँच। इन अतिरिक्त विशेषताओं का उद्देश्य दक्षता बनाए रखते हुए पॉइंटर्स के दुरुपयोग के कारण होने वाले कीड़ों को कम करना है। स्मार्ट पॉइंटर्स आमतौर पर उन वस्तुओं पर नज़र रखते हैं जिन्हें वे स्मृति प्रबंधन के उद्देश्य से इंगित करते हैं।

पॉइंटर्स का दुरुपयोग बग्स का एक प्रमुख स्रोत है: निरंतर आवंटन, डीलक्लोकेशन और रेफ़रिंग जो कि पॉइंटर्स का उपयोग करके लिखे गए प्रोग्राम द्वारा किया जाना चाहिए, जोखिम का परिचय देता है कि मेमोरी लीक होगा। स्मार्ट पॉइंटर्स रिसोर्स लीक को ऑटोमैटिक बनाकर मेमोरी लीक्स को रोकने की कोशिश करते हैं: जब ऑब्जेक्ट को पॉइंटर (या पॉइंटर्स की सीरीज़ में आखिरी) नष्ट हो जाता है, उदाहरण के लिए क्योंकि यह स्कोप से बाहर जाता है, तो पॉइंटेड ऑब्जेक्ट भी नष्ट हो जाता है।

C ++ में कचरा संग्रहण और मेमोरी लीक को रोकने (सिर्फ दो का नाम) पर जोर दिया जाएगा। पॉइंटर्स भाषा का एक मूलभूत हिस्सा हैं, इसलिए प्रोग्रामों के सबसे ट्रिटिव को छोड़कर उनका उपयोग करना बहुत असंभव है।


22
आमतौर पर शास्त्रीय अर्थों में इसका कड़ाई से कचरा संग्रह नहीं, अधिक संदर्भ गिनती। कम से कम स्मार्ट ptr में मैं ([बूस्ट | std] :: साझा_प्ट्र) का उपयोग कर रहा हूँ
डग टी।

3
यह उत्तर स्मार्ट पॉइंटर तक बहुत सीमित है, जो समस्या का केवल एक छोटा पहलू है। इसके अतिरिक्त, स्मार्ट पॉइंटर कचरा संग्रह नहीं हैं।
डेडलिंक

3
इसके अलावा सामान्य में RAII।
Kl

3
नहीं, इसका मतलब यह नहीं है। यह केवल एक पहलू है, और सबसे महत्वपूर्ण नहीं है।
कोनराड रुडोल्फ

मुझे लगता है कि स्मार्ट पॉइंटर्स सबसे महत्वपूर्ण पहलू हैं, लेकिन मैं मानता हूं कि कई अन्य हैं।
डेडएमजी सेप

97

चूँकि मैं वह हूँ जिसने पोलमिक "f * cking पॉइंटर्स" का उपयोग नहीं किया है। मुझे लगता है कि मुझे यहाँ टिप्पणी करनी चाहिए।

सबसे पहले, एक बहुवचन के रूप में यह स्पष्ट रूप से एक चरम दृष्टिकोण का प्रतिनिधित्व करता है। वहाँ रहे हैं निश्चित रूप से (कच्चे) संकेत के वैध का उपयोग करता है। लेकिन मैं (और कई पेशेवर C ++ प्रोग्रामर) यह सुनिश्चित करता हूं कि ये मामले अत्यधिक दुर्लभ हैं। लेकिन हम वास्तव में क्या मतलब है निम्नलिखित है:

प्रथम:

रॉ पॉइंटर्स को किसी भी परिस्थिति में अपनी स्मृति के अधीन नहीं होना चाहिए।

यहां, "स्वयं की स्मृति" का अनिवार्य रूप से मतलब है कि किसी बिंदु deleteपर उस पॉइंटर पर बुलाया जाता है (लेकिन यह उससे अधिक सामान्य है)। यह कथन सुरक्षित रूप से एक निरपेक्ष के रूप में लिया जा सकता है। केवल जब अपने स्वयं के स्मार्ट सूचक (या अन्य स्मृति प्रबंधन रणनीति) को लागू करने अपवाद नहीं है। और यहां तक कि वहाँ आप सामान्य रूप से करना चाहिए अभी भी एक स्मार्ट सूचक निम्न स्तर पर इस्तेमाल करते हैं।

इसके लिए तर्क काफी सरल है: कच्चे संकेत जो स्वयं की स्मृति त्रुटि का एक स्रोत पेश करते हैं। और ये त्रुटियां मौजूदा सॉफ्टवेयर में प्रबल हैं: मेमोरी लीक और डबल विलोपन - अस्पष्ट संसाधन स्वामित्व का एक सीधा परिणाम (लेकिन विपरीत दिशा में जाना)।

यह समस्या पूरी तरह से वास्तव में कोई कीमत पर समाप्त किया जा सकता,, बस स्मार्ट बजाय संकेत कच्चे संकेत का उपयोग करके (चेतावनी: यह अभी भी निश्चित रूप से सोच, की आवश्यकता है, साझा संकेत कर सकते हैं मेमोरी लीक करने के लिए एक बार फिर से चक्र करने के लिए नेतृत्व और इस प्रकार है - लेकिन यह आसानी से है परिहार्य)।

दूसरा:

C ++ में संकेत के अधिकांश उपयोग अनावश्यक हैं।

अन्य भाषाओं के विपरीत, C ++ में मूल्य शब्दार्थ के लिए बहुत मजबूत समर्थन है और बस संकेत की अप्रत्यक्षता की आवश्यकता नहीं है। यह तुरंत महसूस नहीं किया गया था - ऐतिहासिक रूप से, C ++ को C में आसान ऑब्जेक्ट ओरिएंटेशन की सुविधा के लिए आविष्कार किया गया था, और पॉइंट ग्राफ़ द्वारा कनेक्ट किए गए ऑब्जेक्ट ग्राफ़ के निर्माण पर बहुत अधिक निर्भर करता था। लेकिन आधुनिक सी ++ में, यह प्रतिमान शायद ही कभी सबसे अच्छा विकल्प होता है, और आधुनिक सी ++ मुहावरों को अक्सर संकेत की आवश्यकता नहीं होती है । वे संकेत के बजाय मूल्यों पर काम करते हैं ।

दुर्भाग्य से, यह संदेश अभी भी C ++ उपयोगकर्ता समुदाय के बड़े हिस्से में नहीं पकड़ा गया है। परिणामस्वरूप, C ++ का अधिकांश कोड जो अभी भी लिखा गया है, अभी भी अतिशयोक्तिपूर्ण बिंदुओं से अटा पड़ा है, जो कोड को जटिल, धीमा और दोषपूर्ण / अविश्वसनीय बनाता है।

किसी ऐसे व्यक्ति के लिए जो आधुनिक C ++ जानता है, यह स्पष्ट है कि आपको किसी भी बिंदु की आवश्यकता है (या तो स्मार्ट या कच्चे, सिवाय इसके कि इसे पुनरावृत्तियों के रूप में उपयोग करते हुए)। परिणामस्वरूप कोड छोटा, कम जटिल, अधिक पठनीय, अक्सर अधिक कुशल और अधिक विश्वसनीय होता है।


5
आह ... यह वास्तव में 30+ upvotes के साथ उत्तर होना चाहिए ... विशेष रूप से दूसरे बिंदु के लिए। आधुनिक सी ++ में संकेत केवल आवश्यक भी हैं ।
चार्ल्स सल्विया

1
उदाहरण के लिए क्या। गुई वस्तु डॉक्टर वस्तुओं का एक समूह है। इसका संकेत दोनों के रूप में है ताकि वर्ग को आगे घोषित किया जा सके (recompiles से बचा जा सके) और ताकि किसी खाली अवस्था में स्टैक पर बनाए जाने की बजाय (नए के साथ) ऑब्जेक्ट को इनिशियलाइज़ किया जा सके और फिर बाद में फाइल किया जा सके? यह संकेत का पूरी तरह से वैध उपयोग लगता है - क्या सभी एनकैप्सुलेटेड ऑब्जेक्ट्स ढेर पर नहीं होना चाहिए?
मार्टिन बेकेट

4
@ मर्टिन जीयूआई ऑब्जेक्ट एक ऐसा मामला है जहां पॉइंटर ऑब्जेक्ट ग्राफ़ वास्तव में सबसे अच्छा समाधान है। लेकिन स्मृति के स्वामित्व वाले कच्चे पॉइंटर्स के खिलाफ निर्णय अभी भी खड़ा है। या तो साझा पॉइंटर्स का उपयोग करें या एक उचित स्वामित्व मॉडल विकसित करें और कच्चे पॉइंटर्स के माध्यम से नियंत्रणों के बीच केवल कमजोर (= गैर-स्वामित्व) संबंध रखें।
कोनराड रुडोल्फ

1
@ VF1 std::unique_ptr। भी, क्यों नहीं ptr_vec? लेकिन आम तौर पर एक मूल्य वेक्टर अभी भी तेजी से स्वैप होगा (विशेष रूप से चाल शब्दार्थ के साथ)।
कोनराड रूडोल्फ

1
@gaazkam किसी ने आपको केवल मानक कंटेनरों का उपयोग करने के लिए मजबूर नहीं किया। उदाहरण के लिए बूस्ट में अपूर्ण प्रकारों के समर्थन के साथ एक मानचित्र कार्यान्वयन है। एक अन्य उपाय प्रकार के क्षरण का उपयोग करना है; boost::variantएक के साथ एक recursive_wrapperDAG का प्रतिनिधित्व करने के लिए शायद मेरा पसंदीदा समाधान है।
कोनराड रुडोल्फ

15

केवल इसलिए कि आपके लिए उपलब्ध सार हैं जो पॉइंटर्स का उपयोग करने के अधिक मनमौजी पहलुओं को छिपाते हैं, जैसे कि कच्ची मेमोरी तक पहुंच और आपके आवंटन के बाद सफाई। RAII जैसे स्मार्ट पॉइंटर्स, कंटेनर क्लासेस और डिज़ाइन पैटर्न के साथ, कच्चे पॉइंटर्स का उपयोग करने की आवश्यकता कम हो जाती है। उस ने कहा, किसी भी अमूर्तता की तरह, आपको यह समझना चाहिए कि वास्तव में उनके परे जाने से पहले वे कैसे काम करते हैं।


11

अपेक्षाकृत बस, सी मानसिकता "एक समस्या है? एक सूचक का उपयोग करें"। आप इसे C स्ट्रिंग्स, फंक्शन पॉइंटर्स, पॉइंटर्स-ए-इटरेटर्स, पॉइंटर-टू-पॉइंटर, वोड पॉइंटर- यहां तक ​​कि C ++ के शुरुआती दिनों में मेंबर पॉइंटर्स के साथ देख सकते हैं।

लेकिन C ++ में आप इनमें से कई या सभी कार्यों के लिए मानों का उपयोग कर सकते हैं। एक समारोह अमूर्त की आवश्यकता है? std::function। यह एक ऐसा मान है जो एक फ़ंक्शन है। std::string? यह एक मूल्य है, यह एक स्ट्रिंग है। आप C ++ पर समान दृष्टिकोण देख सकते हैं। यह कोड को मनुष्यों और संकलक दोनों के लिए काफी हद तक आसान बना देता है।


C ++ में: कोई समस्या है? एक सूचक का उपयोग करें। अब आपको 2 समस्याएं हैं ...
डैनियल ज़ज़ुला

10

कारणों में से एक संकेत की व्यापक अनुप्रयोग है। उनका उपयोग कंटेनरों पर पुनरावृत्ति के लिए किया जा सकता है, बड़ी वस्तुओं की नकल करने से बचने के लिए जब फ़ंक्शन, गैर-तुच्छ जीवन-समय प्रबंधन, स्मृति में यादृच्छिक स्थानों तक पहुंच आदि, और एक बार जब आप उन्हें एक उद्देश्य के लिए उपयोग करते हैं, तो उनकी अन्य सुविधाएँ उपलब्ध हो जाती हैं। इरादे पर तुरंत स्वतंत्र।

सटीक उद्देश्य के लिए एक उपकरण का चयन कोड को सरल बनाता है और इरादे को अधिक दृश्यमान बनाता है - पुनरावृत्तियों के लिए पुनरावृत्तियां, जीवन-समय प्रबंधन के लिए स्मार्ट संकेत, आदि।


3

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


2

@Jmquigley पॉइंटर और पॉइंटर अंकगणित द्वारा बताई गई मेमोरी लीक के खतरे के अलावा समस्याग्रस्त माना जा सकता है क्योंकि पॉइंटर्स हर जगह मेमोरी में "बग ढूंढने में मुश्किल" और "सुरक्षा भेद्यता" का कारण बन सकते हैं।

यही कारण है कि उन्हें सी # और जावा में लगभग छोड़ दिया गया था।


उम्मीद करें कि वे C # में "निरस्त" नहीं थे। यह उत्तर खराब है, भयानक वर्तनी है, और एक भयानक गलत बयान है।
रामहुंड

1
उन्हें लगभग छोड़ दिया गया। मैं मूल वक्ता से माफी नहीं मांगता।
k3b

1
अरे, हम वर्तनी में मदद कर सकते हैं। क्या आपका मतलब उम्मीद या सिवाय कहने से है?
DeveloperDon

1
C # में लगभग छोड़ दिया गया, आप अभी भी unsafeकीवर्ड निर्दिष्ट करके पॉइंटर को सक्षम कर सकते हैं
linquize

-1

C ++ , C , फीचर्स, प्लस ऑब्जेक्ट्स और क्लासेस को सपोर्ट करता है । सी में पहले से ही पॉइंटर्स और अन्य सामान थे।

पॉइंटर्स एक बहुत ही उपयोगी तकनीक है, जिसे ऑब्जेक्ट ओरिएंटेशन के साथ जोड़ा जा सकता है, और C ++ उनका समर्थन करता है। लेकिन, यह तकनीक, सिखाना मुश्किल है और समझना मुश्किल है, और अवांछित त्रुटियों का कारण बनना बहुत आसान है।

कई नई प्रोग्रामिंग भाषाएं ऑब्जेक्ट्स के साथ पॉइंटर्स का उपयोग नहीं करने का नाटक करती हैं, जैसे जावा, .NET, डेल्फी, वाला, पीएचपी, स्काला। लेकिन, पॉइंटर्स अभी भी उपयोग किए जाते हैं, "पर्दे के पीछे"। इन "हिडन पॉइंटर" तकनीकों को "संदर्भ" कहा जाता है।

वैसे भी, मैं सूचक (ओं) को एक प्रोग्रामिंग पैटर्न के रूप में मानता हूं, कुछ समस्याओं को हल करने के लिए एक वैध तरीका है, साथ ही ऑब्जेक्ट ओरिएंटेड प्रोग्राम करता है।

अन्य डेवलपर्स की राय अलग हो सकती है। लेकिन, मेरा सुझाव है कि छात्र और प्रोग्रामर सीखें:

(1) ऑब्जेक्ट के बिना पॉइंटर्स का उपयोग करें

(२) बिना नुकीले वस्तु

(3) वस्तुओं की ओर स्पष्ट संकेत

(4) ऑब्जेक्ट्स (AKA संदर्भ ) के लिए "छिपा हुआ"; ;-)

उस क्रम में।

भले ही सिखाना मुश्किल हो, और सीखना मुश्किल हो। ऑब्जेक्ट पास्कल (डेल्फी, फ्री पास्कल , अन्य) और C++(जावा या सी # नहीं) का उपयोग उन लक्ष्यों के लिए किया जा सकता है।

और, बाद में, नौसिखिए प्रोग्रामर, "हिडन पॉइंटर्स टू ऑब्जेक्ट्स" प्रोग्रामिंग भाषाओं जैसे: जावा, सी #, ऑब्जेक्ट ओरिएंटेड पीएचपी, और अन्य पर जा सकते हैं।


19
C ++, "C with Classes" की तुलना में पूरी तरह से अधिक है जो इसे शुरू करता है।
डेविड थॉर्नले

आप हवा के उद्धरणों में C ++ और C को क्यों लपेट रहे हैं? और "छिपा हुआ", "संदर्भ" और बाकी सब कुछ? क्या आप "विक्रेता" हैं और "प्रोग्रामिंग" में भाग नहीं ले रहे हैं?
१०

मुझे उन्हें बोल्ड में रखना चाहिए। उद्धरण को उजागर करने के लिए इस्तेमाल किया जा सकता है, लेकिन इसके विपरीत भी
umlcat

-6

VC6 के बारे में बात करते हुए, जब आप किसी वर्ग के पॉइंटर (जो आप इंस्टेंट करते हैं) को एक चर (जैसे DWORD) में डालते हैं, भले ही यह पॉइंटर स्थानीय हो आप सभी कार्यों पर कक्षा तक पहुँच सकते हैं जो समान हीप का उपयोग करते हैं। तात्कालिक वर्ग को स्थानीय के रूप में परिभाषित किया गया है लेकिन वास्तव में ऐसा नहीं है। जहाँ तक मुझे पता है, ढेर चर, संरचना या वर्ग का कोई भी पता होस्टिंग वर्ग के सभी जीवन के साथ अद्वितीय है।

उदाहरण:

class MyClass1 {
    public:
        void A (void);
        void B (void);
        void C (void);
    private:
        DWORD dwclass;
};

class MyClass2 {
    public:
        int C (int i);
};

void MyClass1::A (void) {
    MyClass2 *myclass= new MyClass2;
    dwclass=(DWORD)myclass;
}

void MyClass1::B (void) {
    MyClass2 *myclass= (MyClass2 *)dwclass;
    int i = myclass->C(0); // or int i=((MyClass2 *)dwclass)->C(0);
}

void MyClass1::B (void) {
    MyClass2 *myclass= (MyClass2 *)dwclass;
    delete myclass;
}

संपादित करें कि मूल कोड का बहुत कम हिस्सा। CSRecodset वर्ग केवल CXdbRecordet का कास्टिंग वर्ग है, जहाँ सभी वास्तविक कोड होते हैं। ऐसा करने से मैं उपयोगकर्ता को अपने अधिकारों को खोए बिना लिखे गए लाभों का लाभ उठाने दे सकता हूं। मैं यह प्रदर्शित करने का दिखावा नहीं करता कि मेरा डेटाबेस इंजन पेशेवर है, लेकिन यह वास्तव में काम करता है।

//-------------------------------------
class CSRecordSet : public CSObject
//-------------------------------------
{
public:
    CSRecordSet();
    virtual ~CSRecordSet();
    // Constructor
    bool Create(CSDataBase* pDataBase,CSQueryDef* pQueryDef);
    //Open, find, close
    int OpenRst(bool bReadBlanks=0,bool bCheckLastSql=0,bool bForceLoad=0,bool bMessage=1);     // for a given SQL
    int FindRecord(bool bNext);         // for a given SQL
    // TABLE must be ordered by the same fields that will be seek
    bool SeekRecord(int nFieldIndex, char *key, int length=0);  // CRT bsearch
    bool SeekRecord(int nFieldIndex, long key);     
    bool SeekRecord(int nFieldIndex, double key, int decimals);     
    bool SeekRecord(XSEK *SEK);     
    bool DeleteRecord(void);
    bool Close(void);
    // Record Position:
    bool IsEOF(void);           // pointer out of bound
    bool IsLAST(void);          // TRUE if last record
    bool IsBOF(void);           // pointer out of bound
    bool IsOpen(void);
    bool Move(long lRows);      // returns FALSE if out of bound
    void MoveNextNotEof(void);  // eof is tested
    void MoveNext(void);        // eof is not tested
    void MovePrev(void);        // bof is tested
    void MoveLast(void);
    void MoveFirst(void);
    void SetAbsolutePosition(long lRows);
    long GetAbsolutePosition(void);
    void GoToLast(void); // Restore position after a Filter
    // Table info
    long GetRecordCount(void);
    int GetRstTableNumber(void);
    int GetRecordLength(void); //includes stamp (sizeof char)
    int GetTableType(void);
    // Field info
    int GetFieldCount(void);
    void GetFieldName(int nFieldIndex, char *pbuffer);
    int GetFieldIndex(const char *sFieldName);
    int GetFieldSize(int nFieldIndex);
    int GetFieldDGSize(int nFieldIndex); // String size (i.e. dg_Boolean)
    long GetRecordID(void);
    int GetStandardFieldCount(void);
    bool IsMemoFileTable(void);
    bool IsNumberField(int nFieldIndex);
    int GetFieldType(int nFieldIndex);
    // Read Field value
    bool GetFieldValue(int nFieldIndex, XdbVar& var);
    bool GetFieldValueIntoBuffer(int nFieldIndex,char *pbuffer);
    char *GetMemoField(int nMemoFieldIndex, char *pbuffer, int buf_size);
    bool GetBinaryField(unsigned char *buffer,long *buf_size);
    // Write Field value
    void Edit(void); // required
    bool SetFieldValue(int nFieldIndex, XdbVar& var);
    bool SetFieldValueFromBuffer(int nFieldIndex,const char *pbuffer);
    bool Update(void); // required
    // pointer to the same lpSql
    LPXSQL GetSQL(void);
};

//---------------------------------------------------
CSRecordSet::CSRecordSet(){
//---------------------------------------------------
    pClass |= (CS_bAttach);
}
CSRecordSet::~CSRecordSet(){
    if(pObject) delete (CXdbRecordset*)pObject;
}
bool CSRecordSet::Create(CSDataBase* pDataBase,CSQueryDef* pQueryDef){
    CXdbQueryDef *qr=(CXdbQueryDef*)pQueryDef->GetObject();
    CXdbTables *db=(CXdbTables*)pDataBase->GetObject();
    CXdbRecordset *rst = new CXdbRecordset(db,qr);
    if(rst==NULL) return 0;
    pObject = (unsigned long) rst;
    return 1;
}
bool CSRecordSet::Close(void){
    return ((CXdbRecordset*)pObject)->Close();
}
int CSRecordSet::OpenRst(bool bReadBlanks,bool bCheckLastSql,bool bForceLoad, bool bMessage){
    unsigned long dw=0L;
    if(bReadBlanks) dw|=SQL_bReadBlanks;
    if(bCheckLastSql) dw|=SQL_bCheckLastSql;
    if(bMessage) dw|=SQL_bRstMessage;
    if(bForceLoad) dw|=SQL_bForceLoad;

    return ((CXdbRecordset*)pObject)->OpenEx(dw);
}
int CSRecordSet::FindRecord(bool bNext){
    return ((CXdbRecordset*)pObject)->FindRecordEx(bNext);
}
bool CSRecordSet::DeleteRecord(void){
    return ((CXdbRecordset*)pObject)->DeleteEx();
}
bool CSRecordSet::IsEOF(void){
    return ((CXdbRecordset*)pObject)->IsEOF();
}
bool CSRecordSet::IsLAST(void){
    return ((CXdbRecordset*)pObject)->IsLAST();
}
bool CSRecordSet::IsBOF(void){
    return ((CXdbRecordset*)pObject)->IsBOF();
}
bool CSRecordSet::IsOpen(void){
    return ((CXdbRecordset*)pObject)->IsOpen();
}
bool CSRecordSet::Move(long lRows){
    return ((CXdbRecordset*)pObject)->MoveEx(lRows);
}
void CSRecordSet::MoveNextNotEof(void){
    ((CXdbRecordset*)pObject)->MoveNextNotEof();
}
void CSRecordSet::MoveNext(void){
    ((CXdbRecordset*)pObject)->MoveNext();
}
void CSRecordSet::MovePrev(void){
    ((CXdbRecordset*)pObject)->MovePrev();
}
void CSRecordSet::MoveLast(void){
    ((CXdbRecordset*)pObject)->MoveLast();
}
void CSRecordSet::MoveFirst(void){
    ((CXdbRecordset*)pObject)->MoveFirst();
}
void CSRecordSet::SetAbsolutePosition(long lRows){
    ((CXdbRecordset*)pObject)->SetAbsolutePosition(lRows);
}
long CSRecordSet::GetAbsolutePosition(void){
    return ((CXdbRecordset*)pObject)->m_AbsolutePosition;
}
long CSRecordSet::GetRecordCount(void){
    return ((CXdbRecordset*)pObject)->GetRecordCount();
}
int CSRecordSet::GetFieldCount(void){
    return ((CXdbRecordset*)pObject)->GetFieldCount();
}
int CSRecordSet::GetRstTableNumber(void){
    return ((CXdbRecordset*)pObject)->GetRstTableNumber();
}
void CSRecordSet::GetFieldName(int nFieldIndex, char *pbuffer){
    ((CXdbRecordset*)pObject)->GetFieldName(nFieldIndex,pbuffer);
}
int CSRecordSet::GetFieldIndex(const char *sFieldName){
    return ((CXdbRecordset*)pObject)->GetFieldIndex(sFieldName);
}
bool CSRecordSet::IsMemoFileTable(void){
    return ((CXdbRecordset*)pObject)->IsMemoFileTable();
}
bool CSRecordSet::IsNumberField(int nFieldIndex){
    return ((CXdbRecordset*)pObject)->IsNumberField(nFieldIndex);
}
bool CSRecordSet::GetFieldValueIntoBuffer(int nFieldIndex,char *pbuffer){
    return ((CXdbRecordset*)pObject)->GetFieldValueIntoBuffer(nFieldIndex,pbuffer);
}
void CSRecordSet::Edit(void){
    ((CXdbRecordset*)pObject)->Edit();
}
bool CSRecordSet::Update(void){
    return ((CXdbRecordset*)pObject)->Update();
}
bool CSRecordSet::SetFieldValue(int nFieldIndex, XdbVar& var){
    return ((CXdbRecordset*)pObject)->SetFieldValue(nFieldIndex,var);
}
bool CSRecordSet::SetFieldValueFromBuffer(int nFieldIndex,const char *pbuffer){
    return ((CXdbRecordset*)pObject)->SetFieldValueFromBuffer(nFieldIndex,pbuffer);
}
bool CSRecordSet::GetFieldValue(int nFieldIndex, XdbVar& var){
    return ((CXdbRecordset*)pObject)->GetFieldValue(nFieldIndex,var);
}
bool CSRecordSet::SeekRecord(XSEK *SEK){
    return ((CXdbRecordset*)pObject)->TableSeek(SEK);
}
bool CSRecordSet::SeekRecord(int nFieldIndex,char *key, int length){
    return ((CXdbRecordset*)pObject)->TableSeek(nFieldIndex,key,length);
}
bool CSRecordSet::SeekRecord(int nFieldIndex,long i){
    return ((CXdbRecordset*)pObject)->TableSeek(nFieldIndex,i);
}
bool CSRecordSet::SeekRecord(int nFieldIndex, double d, int decimals)
{
    return ((CXdbRecordset*)pObject)->TableSeek(nFieldIndex,d,decimals);
}
int CSRecordSet::GetRecordLength(void){
    return ((CXdbRecordset*)pObject)->GetRecordLength();
}
char *CSRecordSet::GetMemoField(int nMemoFieldIndex,char *pbuffer, int BUFFER_SIZE){
    return ((CXdbRecordset*)pObject)->GetMemoField(nMemoFieldIndex,pbuffer,BUFFER_SIZE);
}
bool CSRecordSet::GetBinaryField(unsigned char *buffer,long *buf_size){
    return ((CXdbRecordset*)pObject)->GetBinaryField(buffer,buf_size);
}
LPXSQL CSRecordSet::GetSQL(void){
    return ((CXdbRecordset*)pObject)->GetSQL();
}
void CSRecordSet::GoToLast(void){
    ((CXdbRecordset*)pObject)->GoToLast();
}
long CSRecordSet::GetRecordID(void){
    return ((CXdbRecordset*)pObject)->GetRecordID();
}
int CSRecordSet::GetStandardFieldCount(void){
    return ((CXdbRecordset*)pObject)->GetStandardFieldCount();
}
int CSRecordSet::GetTableType(void){
    return ((CXdbRecordset*)pObject)->GetTableType();
}
int CSRecordSet::GetFieldType(int nFieldIndex){
    return ((CXdbRecordset*)pObject)->GetFieldType(nFieldIndex);
}
int CSRecordSet::GetFieldDGSize(int nFieldIndex){
    return ((CXdbRecordset*)pObject)->GetFieldDGSize(nFieldIndex);
}
int CSRecordSet::GetFieldSize(int nFieldIndex){
    return ((CXdbRecordset*)pObject)->GetFieldSize(nFieldIndex);
}

EDIT: डेडएमजी द्वारा अनुरोध:

void nimportequoidumomentquecaroule(void) {

    short i = -4;
    unsigned short j=(unsigned short)i;

}

1
इस विवरण को कुछ कोड द्वारा यह स्पष्ट करने के लिए बढ़ाया जा सकता है कि आप क्या वर्णन कर रहे हैं। मेरा मानना ​​है कि यह मूल प्रश्न से संबंधित है, लेकिन अगर आपने हमें इस परिदृश्य में खतरे की चेतावनी दी है, तो यह प्रश्नकर्ता के विषय को विस्तृत करने में मदद करेगा।
DeveloperDon

1
यह DWORDअपमानजनक है और संभवतः गलत है (DWORD एक संकेतक को रखने के लिए आवश्यक रूप से पर्याप्त चौड़ा नहीं है)। यदि आपको किसी अनपेक्षित पॉइंटर की आवश्यकता है, तो उपयोग करें void*- लेकिन जब आप अपने आप को सी ++ में जरूरत पड़ने पर पाते हैं, तो आपको अक्सर अपने कोड में एक डिजाइन समस्या मिल जाती है जिसे आपको ठीक करना चाहिए।
Mat

साल्वाडोर, मुझे लगता है कि आप VC6 के बारे में कुछ कहना चाह रहे हैं और यह कैसे असामान्य और अप्रत्याशित सूचक हैंडलिंग है। उदाहरण टिप्पणियों से लाभान्वित हो सकता है, और यदि आप संकलक से चेतावनी देख रहे हैं, तो वे आपके प्रश्न से संबंधित उत्तर के संबंध में जानकारीपूर्ण हो सकते हैं।
DeveloperDon

@ यह उदाहरण 32 बिट OS और VC6 ++ कंपाइलर के लिए है।
साल्वाडोर

6
एक बिल्कुल प्राचीन संकलक में खराब कोड के बारे में बात कर रहे हैं? जी नहीं, धन्यवाद।
डेडएमजी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.