क्या केवल फ़ंक्शन ओवरलोडिंग के लिए C ++ कंपाइलर का उपयोग करना बुरा है?
IMHO का दृष्टिकोण, हां, और मुझे इसका उत्तर देने के लिए सिज़ोफ्रेनिक बनने की आवश्यकता होगी क्योंकि मैं दोनों भाषाओं से प्यार करता हूं, लेकिन इसका दक्षता से कोई लेना-देना नहीं है, लेकिन सुरक्षा और मुहावरों का अधिक उपयोग।
C साइड
C दृष्टिकोण से, मुझे लगता है कि आपके कोड को ओवरलोडिंग का उपयोग करने के लिए आपके कोड को C ++ की आवश्यकता होती है। जब तक आप इसे C ++ टेम्प्लेट के साथ स्थैतिक बहुरूपता के लिए उपयोग नहीं कर रहे हैं, यह ऐसी तुच्छ वाक्य रचना है, जो एक पूरी तरह से अलग भाषा में स्विच करने के बदले में प्राप्त की जाती है। इसके अलावा यदि आप कभी भी अपने कार्यों को एक dylib को निर्यात करना चाहते हैं (हो सकता है या एक व्यावहारिक चिंता नहीं हो सकती है), तो आप अब सभी नाम-रूपी प्रतीकों के साथ व्यापक खपत के लिए बहुत व्यावहारिक रूप से नहीं कर सकते हैं।
सी ++ साइड
C ++ के दृष्टिकोण से, आपको C ++ की तरह C का उपयोग फ़ंक्शन ओवरलोडिंग के साथ नहीं करना चाहिए। यह शैलीगत हठधर्मिता नहीं है, बल्कि रोजमर्रा के C ++ के व्यावहारिक उपयोग से संबंधित है।
सी कोड का आपका सामान्य प्रकार केवल यथोचित रूप से समझदार और "सुरक्षित" है यदि आप सी टाइप सिस्टम के खिलाफ काम कर रहे हैं जो कॉपी सीटर जैसी चीजों के लिए मना करता है structs
। एक बार जब आप C ++ की अधिक समृद्ध प्रकार की प्रणाली में काम कर रहे होते हैं, तो दैनिक कार्य जो कि बहुत अधिक मूल्य के होते हैं memset
और memcpy
वे कार्य नहीं बन जाते हैं जिन्हें आपको हर समय झुकना चाहिए। इसके बजाय, वे वे कार्य हैं जो आप आमतौर पर प्लेग की तरह से बचना चाहते हैं, चूंकि सी ++ प्रकार के साथ, आपको उन्हें कच्चे बिट्स और बाइट्स की तरह व्यवहार नहीं करना चाहिए और उन्हें कॉपी और फेरबदल किया जाना चाहिए और मुक्त किया जाना चाहिए। यहां तक कि अगर आपका कोड इस समय केवल memset
आदिम और POD UDTs जैसी चीजों का उपयोग करता है , तब भी कोई भी आपके द्वारा उपयोग किए जाने वाले किसी भी UDT में एक Ctor जोड़ता है (केवल एक सदस्य को जोड़ने के लिए जिसे एक की आवश्यकता होती है, जैसेstd::unique_ptr
सदस्य) इस तरह के कार्यों या एक आभासी फ़ंक्शन या उस तरह के कुछ के खिलाफ, यह आपके सभी सामान्य सी-स्टाइल कोडिंग को अपरिभाषित व्यवहार के लिए अतिसंवेदनशील बनाता है। इसे हर्ब सटर से लें:
memcpy
और memcmp
प्रकार प्रणाली का उल्लंघन। memcpy
वस्तुओं की नकल करना फोटोकॉपीयर का उपयोग करके पैसा बनाने जैसा है। memcmp
वस्तुओं की तुलना करने के लिए उपयोग करना अपने धब्बों को गिनकर तेंदुओं की तुलना करने जैसा है। उपकरण और विधियाँ कार्य करने के लिए प्रकट हो सकती हैं, लेकिन वे इसे स्वीकार करने के लिए बहुत मोटे हैं। C ++ ऑब्जेक्ट्स सभी जानकारी छिपाने के बारे में हैं (यकीनन सॉफ्टवेयर इंजीनियरिंग में सबसे लाभदायक सिद्धांत; आइटम 11 देखें): ऑब्जेक्ट डेटा छिपाते हैं (आइटम 41 देखें) और कंस्ट्रक्टर्स और असाइनमेंट ऑपरेटरों के माध्यम से उस डेटा को कॉपी करने के लिए सटीक सार को समर्पित करें (आइटम 52 से 55 तक देखें) । इन सबके साथ बुलडोज़िंग memcpy
सूचना छिपाना का एक गंभीर उल्लंघन है, और अक्सर स्मृति और संसाधन लीक (सर्वोत्तम रूप से), क्रैश (बदतर), या अपरिभाषित व्यवहार (सबसे खराब) - सी ++ कोडिंग मानकों की ओर जाता है।
इतने सारे सी डेवलपर्स इससे सहमत नहीं हैं और ठीक ही इसलिए, क्योंकि दर्शन केवल तभी लागू होता है यदि आप C ++ में कोड लिख रहे हैं। आप सबसे अधिक संभावना कर रहे हैं कई समस्याएं खड़ी कोड लिखने अगर आप की तरह कार्यों का उपयोग memcpy
हर समय कोड में सी ++ के रूप में बनाता है कि है, लेकिन यह पूरी तरह से ठीक है अगर आप यह कर सी में । टाइप सिस्टम में अंतर के कारण इस संबंध में दो भाषाएँ बहुत अलग हैं। यह बहुत ही आकर्षक है कि इन दोनों की विशेषताओं के सबसेट को देखना आम है और विश्वास है कि एक का उपयोग दूसरे की तरह किया जा सकता है, विशेष रूप से C ++ की तरफ, लेकिन C + कोड (या C-- कोड) आमतौर पर C और C दोनों की तुलना में कहीं अधिक समस्याग्रस्त है। C ++ कोड।
इसी तरह आप malloc
सी-स्टाइल के संदर्भ में (जो कि कोई ईएच का मतलब नहीं है) का उपयोग नहीं करना चाहिए, अगर यह किसी भी सी ++ फ़ंक्शंस को सीधे कॉल कर सकता है, जो तब से आपके फ़ंक्शन में निहित निकास बिंदु के परिणामस्वरूप हो सकता है अपवाद जो आप प्रभावी ढंग से C- स्टाइल कोड लिखने से नहीं पकड़ सकते, free
उस मेमोरी में सक्षम होने से पहले । तो जब भी आप सी के रूप में एक साथ ++ बनाता है कि एक फ़ाइल .cpp
एक्सटेंशन या जो कुछ भी है और यह जैसी चीजों के इन सभी प्रकार करता है malloc
, memcpy
, memset
,qsort
, आदि, तो यह लाइन के आगे समस्याओं के लिए पूछ रहा है यदि पहले से ही नहीं है जब तक कि यह एक वर्ग का कार्यान्वयन विवरण नहीं है जो केवल आदिम प्रकारों के साथ काम करता है, जिस बिंदु पर यह अभी भी अपवाद-सुरक्षित होने के लिए अपवाद-हैंडलिंग करने की आवश्यकता है। आप सी ++ कोड लिख रहे हैं आप के बजाय आम तौर पर आरए II पर भरोसा करते हैं और तरह बातें उपयोग करना चाहते हैं vector
, unique_ptr
, shared_ptr
, आदि, और जब संभव हो सभी सामान्य सी-शैली कोडिंग से बचें।
कारण आप सी और एक्स-रे डेटा प्रकारों में रेजर ब्लेड के साथ खेल सकते हैं और एक टीम में संपार्श्विक क्षति पैदा करने के लिए प्रवण होने के बिना अपने बिट्स और बाइट्स के साथ खेल सकते हैं (हालांकि आप अभी भी अपने आप को किसी भी तरह से चोट पहुँचा सकते हैं) सी के कारण नहीं है प्रकार कर सकते हैं, लेकिन इस वजह से कि वे कभी नहीं कर पाएंगे। जिस क्षण आप सी + + प्रणाली का विस्तार करते हैं, जिसमें सी + + जैसे फीचर्स शामिल होते हैं जैसे कि सीटर, डावर्स, और वीटैबल्स, अपवाद-हैंडलिंग के साथ, सभी मुहावरेदार सी कोड का प्रतिपादन किया जाएगा, जो वर्तमान में कहीं अधिक खतरनाक है, और आपको एक नया प्रकार दिखाई देगा दर्शन और मानसिकता विकसित करना जो कोडिंग की एक पूरी तरह से अलग शैली को प्रोत्साहित करेगा, जैसा कि आप सी ++ में देखते हैं, जो अब एक वर्ग के लिए एक कच्चे सूचक कदाचार का उपयोग करने पर भी विचार करता है जो स्मृति का विरोध करता है, जैसा कि आरएआई-अनुरूप संसाधन unique_ptr
। वह मानसिकता सुरक्षा की पूर्ण भावना से विकसित नहीं हुई। यह इस बात से विकसित हुआ कि सी + + को विशेष रूप से उन अपवादों से निपटने के लिए सुरक्षित होने की आवश्यकता है जो दिए गए अपवाद-हैंडलिंग जैसे कि यह केवल इसके प्रकार प्रणाली के माध्यम से अनुमति देता है।
अपवाद-सुरक्षा
फिर, जिस क्षण आप C ++ भूमि में होते हैं, लोग आपके कोड को अपवाद-सुरक्षित होने की उम्मीद करने जा रहे हैं। लोग आपके कोड को भविष्य में बनाए रख सकते हैं, यह देखते हुए कि यह पहले से ही C ++ में लिखा और संकलित है, और बस std::vector, dynamic_cast, unique_ptr, shared_ptr
कोड में आदि का उपयोग करते हैं , जिसे आपके कोड द्वारा प्रत्यक्ष या अप्रत्यक्ष रूप से कहा जाता है, यह मानते हुए कि आपका कोड पहले से ही "C ++" है। कोड। उस बिंदु पर हमें उस मौके का सामना करना होगा जो चीजें फेंक देंगे, और फिर जब आप इस तरह पूरी तरह से ठीक और प्यारा सी कोड लेंगे:
int some_func(int n, ...)
{
int* x = calloc(n, sizeof(int));
if (x)
{
f(n, x); // some function which, now being a C++ function, may
// throw today or in the future.
...
free(x);
return success;
}
return fail;
}
... अब टूट गया है। अपवाद-सुरक्षित होने के लिए इसे फिर से लिखना होगा:
int some_func(int n, ...)
{
int* x = calloc(n, sizeof(int));
if (x)
{
try
{
f(n, x); // some function which, now being a C++ function, may
// throw today or in the future (maybe someone used
// std::vector inside of it).
}
catch (...)
{
free(x);
throw;
}
...
free(x);
return success;
}
return fail;
}
कुल! यही कारण है कि ज्यादातर सी ++ डेवलपर्स इसके बजाय यह मांग करेंगे:
void some_func(int n, ...)
{
vector<int> x(n);
f(x); // some function which, now being a C++ function, may throw today
// or in the future.
}
उपरोक्त RAII-अनुरूप अपवाद-सुरक्षित कोड है जो C ++ डेवलपर्स आमतौर पर स्वीकृत करेगा क्योंकि फ़ंक्शन लीक नहीं करेगा, जिसके परिणामस्वरूप कोड की कौन सी पंक्ति ट्रिगर नहीं होती है, जिसके परिणामस्वरूप throw
।
एक भाषा चुनें
आपको या तो RAII, अपवाद-सुरक्षा, टेम्प्लेट, OOP, आदि के साथ C ++ के टाइप सिस्टम और दर्शन को गले लगाना चाहिए या C को गले लगाना चाहिए जो मोटे तौर पर कच्चे बिट्स और बाइट्स के आसपास घूमता है। आपको इन दो भाषाओं के बीच एक अपवित्र विवाह नहीं करना चाहिए, और उन्हें अलग-अलग भाषाओं में अलग-अलग करने के बजाय उन्हें एक साथ धुंधला करने के लिए अलग-अलग व्यवहार करना चाहिए।
ये भाषाएं आपसे शादी करना चाहती हैं। आप आम तौर पर डेटिंग के बजाय एक को चुनते हैं और दोनों के साथ बेवकूफ बनाते हैं। या आप मेरी तरह एक बहुविवाहक हो सकते हैं और दोनों से शादी कर सकते हैं, लेकिन आपको अपनी सोच को पूरी तरह से बदलना होगा जब एक दूसरे के साथ समय बिताएं और उन्हें एक-दूसरे से अच्छी तरह से अलग रखें ताकि वे एक-दूसरे से लड़ें नहीं।
बाइनरी आकार
जिज्ञासा से बाहर मैंने अपनी मुफ्त सूची के कार्यान्वयन और बेंचमार्क को अभी लेने की कोशिश की और इसे सी ++ में पोर्ट किया क्योंकि जब से मैं वास्तव में इसके लिए उत्सुक हुआ:
[...] पता नहीं है कि यह सी के लिए कैसा लगेगा क्योंकि मैं सी कंपाइलर का उपयोग नहीं कर रहा हूं।
... और जानना चाहता था कि क्या बाइनरी आकार C ++ के रूप में सभी इमारत में बढ़ेगा। इसने मुझे सभी जगहों पर स्पष्ट जातियों को छिड़कने की आवश्यकता थी, जो वास्तव में एक कारण था (एक कारण मुझे वास्तव में सी में बेहतर स्तर के आवंटन और डेटा संरचना जैसी चीजें लिखना पसंद था) लेकिन केवल एक मिनट लगा।
सिर्फ सी के साथ यह निर्माण और, का उपयोग करते हुए कहते हैं के बीच का अंतर, - यह सिर्फ एक सरल सांत्वना अनुप्रयोग के लिए और कोड है कि किसी भी सी ++ सुविधाओं, यहां तक कि नहीं ऑपरेटर ओवरलोडिंग का प्रयोग नहीं करते एक MSVC 64-बिट रिलीज निर्माण की तुलना की गई थी <cstdlib>
के बजाय <stdlib.h>
और इस तरह की चीजें, लेकिन मुझे यह जानकर आश्चर्य हुआ कि यह द्विआधारी आकार में शून्य अंतर था!
बाइनरी 9,728
बाइट्स जब यह C में बनाया गया था, और इसी तरह 9,278
बाइट्स जब C ++ कोड के रूप में संकलित किया गया था। मुझे वास्तव में इसकी उम्मीद नहीं थी। मुझे लगा कि ईएच जैसी चीजें कम से कम वहां थोड़ी-बहुत जोड़ देंगी (सोचा कि यह कम से कम सौ बाइट्स की तरह अलग होगी), हालांकि शायद यह पता लगाने में सक्षम था कि ईएच से संबंधित निर्देशों को जोड़ने की कोई जरूरत नहीं है क्योंकि मैं अभी हूं सी मानक पुस्तकालय का उपयोग कर और कुछ भी नहीं फेंकता है। मैंने कुछ सोचाआरटीटीआई की तरह, द्विआधारी आकार में थोड़ा सा जोड़ देगा। वैसे भी, यह देखने के लिए बहुत अच्छा था। बेशक, मुझे नहीं लगता कि आपको इस एक परिणाम से सामान्यीकरण करना चाहिए, लेकिन इसने मुझे कम से कम प्रभावित किया। इसने बेंचमार्क पर भी कोई प्रभाव नहीं डाला, और स्वाभाविक रूप से इसलिए, क्योंकि मैं कल्पना करता हूं कि समान परिणामी बाइनरी आकार का मतलब समान परिणामी मशीन निर्देश भी था।
उस ने कहा, जो ऊपर वर्णित सुरक्षा और इंजीनियरिंग मुद्दों के साथ द्विआधारी आकार की परवाह करता है? इसलिए फिर से, एक भाषा चुनें और उसके दर्शन को अपनाने की कोशिश करने के बजाय उसके दर्शन ग्रहण करें; मैं यही सलाह देता हूं।
//
टिप्पणी कर सकूं। अगर यह काम करता है, तो क्यों नहीं?