अंतिम व्यक्ति मूर्खतापूर्ण है क्योंकि यह प्रारंभ होने पर प्रारंभिकरण का उपयोग नहीं करता है।
पहले दो पूरी तरह से समान रूप से समान हैं (c_str()
सदस्य फ़ंक्शन के बारे में सोचें), इसलिए पहले संस्करण को प्राथमिकता दें क्योंकि यह सबसे प्रत्यक्ष और बेवकूफ है, और पढ़ने के लिए सबसे आसान है।
(वहाँ एक अर्थ अंतर अगर std::string
एक constexpr
डिफ़ॉल्ट निर्माता था हो सकता है, लेकिन यह नहीं है। फिर भी, यह संभव है कि std::string()
std::string("")
से अलग है, लेकिन मैं किसी भी कार्यान्वयन करना है कि पता नहीं है यही नहीं, यह भावना का एक बहुत बनाने के लिए लग रहे हैं के बाद से नहीं है। दूसरी ओर, लोकप्रिय छोटे स्ट्रिंग अनुकूलन आजकल मतलब है कि दोनों संस्करणों शायद नहीं किसी भी गतिशील आवंटन प्रदर्शन करेंगे।)
अद्यतन: @Jonathan बताते हैं के रूप में, दो स्ट्रिंग कंस्ट्रक्टर्स शायद अलग कोड निष्पादित होगा, और है कि अगर आप के लिए मायने रखती है (हालांकि यह वास्तव में नहीं होना चाहिए), तो आप एक चौथे संस्करण की सोच सकते हैं:
: cstr ? cstr : std::string()
दोनों पठनीय और डिफ़ॉल्ट निर्माण।
दूसरा अद्यतन: लेकिन cstr ? cstr : ""
पसंद करते हैं। जैसा कि आप नीचे देख सकते हैं, जब दोनों शाखाएं समान कन्स्ट्रक्टर को कॉल करती हैं, तो इसे सशर्त चालों और कोई शाखाओं का उपयोग करके बहुत कुशलतापूर्वक कार्यान्वित किया जा सकता है। (तो दो संस्करणों वास्तव में अलग अलग कोड उत्पन्न करते हैं, लेकिन पहले एक बेहतर है।)
गिगल्स के लिए, मैं बजना 3 के माध्यम से दोनों संस्करणों को चलाने गए हैं।3, -O3
, x86_64 पर, एक struct foo;
तुम्हारा और एक समारोह foo bar(char const * p) { return p; }
तरह के लिए के साथ:
डिफ़ॉल्ट निर्माता (std::string()
):
.cfi_offset r14, -16
mov R14, RSI
mov RBX, RDI
test R14, R14
je .LBB0_2
mov RDI, R14
call strlen
mov RDI, RBX
mov RSI, R14
mov RDX, RAX
call _ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm
jmp .LBB0_3
.LBB0_2:
xorps XMM0, XMM0
movups XMMWORD PTR [RBX], XMM0
mov QWORD PTR [RBX + 16], 0
.LBB0_3:
mov RAX, RBX
add RSP, 8
pop RBX
pop R14
ret
खाली स्ट्रिंग निर्माता (""
):
.cfi_offset r14, -16
mov R14, RDI
mov EBX, .L.str
test RSI, RSI
cmovne RBX, RSI
mov RDI, RBX
call strlen
mov RDI, R14
mov RSI, RBX
mov RDX, RAX
call _ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm
mov RAX, R14
add RSP, 8
pop RBX
pop R14
ret
.L.str:
.zero 1
.size .L.str, 1
मेरे मामले में, यह भी दिखाई देगा कि ""
बेहतर कोड उत्पन्न करता है: दोनों संस्करण strlen
पर कॉल करते हैं, लेकिन खाली-स्ट्रिंग संस्करण किसी भी कूद का उपयोग नहीं करता है, केवल सशर्त चाल (क्योंकि उसी कन्स्ट्रक्टर को केवल दो अलग-अलग तर्कों के साथ कहा जाता है)। बेशक यह एक पूरी तरह से अर्थहीन, गैर-पोर्टेबल और गैर-हस्तांतरणीय अवलोकन है, लेकिन यह दिखाता है कि संकलक को हमेशा जितनी मदद हो सकती है उतनी मदद की आवश्यकता नहीं होती है। बस सबसे अच्छा दिखने वाला कोड लिखें।
यह सब उस पर निर्भर करता है कि आप एक नलप्टर का मतलब क्या चाहते हैं। क्या यह आपके लिए खाली स्ट्रिंग जैसा ही है, या इसका अलग अर्थ होना चाहिए? – PlasmaHH
मुझे लगता है कि आपको पहले विकल्प का उपयोग करना चाहिए क्योंकि आप केवल एक बार स्ट्रिंग के कन्स्ट्रक्टर को कॉल करते हैं। – Alexis
@PlasmaHH ठीक है, मैं चाहता हूं कि कोड स्निपेट क्या करे, जब चार सूचक न्यूल हो। – hyde