c++ - আউটপুট স্ট্রিমগুলির জন্য "\ n" কেন "\ n" এর চেয়ে বেশি পছন্দ?




performance cout (3)

'\ N' এর পরিবর্তে আরও পাঠযোগ্যতার জন্য std :: endl ব্যবহার করার পরামর্শ দেওয়া হয় না।

this উত্তরে আমরা এটি পড়তে পারি:

আমি মনে করি '\n' ব্যবহার করতে বা "\n" ব্যবহারের মধ্যে সামান্য পার্থক্য রয়েছে, তবে পরবর্তীটি (দুটি) অক্ষরের একটি অ্যারে, যা অক্ষর অনুসারে একটি মুদ্রণ করতে হবে, যার জন্য একটি লুপ সেট আপ করতে হবে, যা একটি একক অক্ষর আউটপুট চেয়ে জটিল

জোর আমার

যে আমার জ্ঞান করে তোলে। আমি মনে করি যে কনস্টের const char* আউটপুট করার জন্য একটি লুপ দরকার যা নাল-টার্মিনেটরের জন্য পরীক্ষা করবে, যা বলা উচিত একটি সহজ putchar (যে std::cout প্রতিনিধিদের সাথে এটি কল করার জন্য বোঝায় না - এটি কেবল একটি উদাহরণ উপস্থাপনের একটি সরলীকরণ)।

এটি আমাকে ব্যবহার করতে রাজি করল

std::cout << '\n';
std::cout << ' ';

বরং

std::cout << "\n";
std::cout << " ";

এখানে এখানে উল্লেখ করার মতো বিষয় যে আমি পারফরম্যান্সের পার্থক্যটি বেশ নগণ্য বলে সচেতন। তবুও, কিছু যুক্তি দিতে পারে যে প্রাক্তন পদ্ধতির মধ্যে একটি স্ট্রিং আক্ষরিকের চেয়ে বরং একটি চরিত্রকে উত্তীর্ণ করার অভিপ্রায় নিয়ে আসে যা কেবল ' char দীর্ঘ '\0' গণনা করা হয়)

ইদানীং আমি কারওর জন্য কিছুটা সামান্য কোড রিভিউস সম্পন্ন করেছি যারা পরবর্তী পদ্ধতিটি ব্যবহার করছিল। আমি মামলায় একটি ছোট মন্তব্য করে এগিয়ে গেলাম। তখন বিকাশকারী আমাকে ধন্যবাদ জানিয়েছিলেন এবং বলেছিলেন যে তিনি এমন পার্থক্যের কথাও ভাবেননি (মূলত অভিপ্রায়কে কেন্দ্র করে)। এটি মোটেও কার্যকর ছিল না (আশ্চর্যজনকভাবে), তবে পরিবর্তনটি গৃহীত হয়েছিল।

আমি তখন ভাবতে শুরু করি যে পরিবর্তনটি কীভাবে তাৎপর্যপূর্ণ, তাই আমি দৌড়ে গেলাম গডবোল্টে। আমার অবাক করে দিয়ে, -std=c++17 -O3 (ট্রাঙ্ক) -std=c++17 -O3 পতাকা সহ পরীক্ষা করার সময় এটি নিম্নলিখিত ফলাফলগুলি দেখিয়েছিল। নিম্নলিখিত কোডের জন্য উত্পন্ন সমাবেশ:

#include <iostream>

void str() {
    std::cout << "\n";
}

void chr() {
    std::cout << '\n';
}

int main() {
    str();
    chr();
}

আমাকে অবাক করে দিয়েছিল, কারণ দেখা যাচ্ছে যে chr() আসলে str() চেয়ে দ্বিগুণ নির্দেশাবলীর উত্পন্ন করছে:

.LC0:
        .string "\n"
str():
        mov     edx, 1
        mov     esi, OFFSET FLAT:.LC0
        mov     edi, OFFSET FLAT:_ZSt4cout
        jmp     std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
chr():
        sub     rsp, 24
        mov     edx, 1
        mov     edi, OFFSET FLAT:_ZSt4cout
        lea     rsi, [rsp+15]
        mov     BYTE PTR [rsp+15], 10
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        add     rsp, 24
        ret

তা কেন? কেন উভয়ই শেষ পর্যন্ত একই std::basic_ostream ফাংশনটিকে std::basic_ostream const char* যুক্তির সাথে কল করে? এর অর্থ কি এই যে char আক্ষরিক দৃষ্টিভঙ্গি কেবল ভাল নয় , তবে স্ট্রিং আক্ষরিক চেয়েও খারাপ ?


অন্য উত্তরগুলির মধ্যে কোনওটিই সত্যিই ব্যাখ্যা করে না যে সংকলকটি আপনার গডবোল্ট লিঙ্কে কোডটি কেন জেনারেট করে, তাই আমি ভেবেছিলাম যে আমি চিপ করব।

আপনি যদি উত্পন্ন কোডটি দেখে থাকেন তবে আপনি এটি দেখতে পারেন:

std::cout << '\n';

কম্পাইল করে নিচে, বাস্তবে:

char c = '\n';
std::cout.operator<< (&c, 1);

এবং এই কাজটি করার জন্য, chr() ক্রিয়া chr() জন্য একটি স্ট্যাক ফ্রেম তৈরি করতে হবে, যেখানে অতিরিক্ত নির্দেশাবলীর অনেকগুলি আসে।

অন্যদিকে, এটি সংকলন করার সময়:

std::cout << "\n";

str() 'টেল কল' operator<< (const char *) জন্য str() কে অনুকূলিত করতে পারে, যার অর্থ কোনও স্ট্যাক ফ্রেমের প্রয়োজন হয় না।

সুতরাং আপনার ফলাফলগুলি কিছুটা তত্পর হয়ে পড়েছে যে আপনি operator<< পৃথক ফাংশনগুলিতে কল রেখেছিলেন। এই কলগুলিকে ইনলাইন করা আরও প্রকাশ্য, দেখুন: https://godbolt.org/z/OO-8dS

এখন আপনি দেখতে পাচ্ছেন, '\n' আউটপুট দেওয়ার সময় আরও কিছুটা ব্যয়বহুল (কারণ ofstream::operator<< (char) ) এর জন্য কোনও নির্দিষ্ট ওভারলোড নেই, তবে আপনার উদাহরণের চেয়ে পার্থক্যটি কম চিহ্নিত হয়েছে।


হ্যাঁ, এই নির্দিষ্ট প্রয়োগের জন্য, উদাহরণস্বরূপ, char সংস্করণ স্ট্রিং সংস্করণের চেয়ে কিছুটা ধীর।

উভয় সংস্করণ একটি write(buffer, bufferSize) স্টাইল ফাংশন কল করে। স্ট্রিং সংস্করণের জন্য, bufferSize সংকলন সময়ে (1 বাইট) নামে পরিচিত, তাই শূন্য টার্মিনেটর রান-টাইম খুঁজে পাওয়ার দরকার নেই। char সংস্করণটির জন্য, সংকলকটি স্ট্যাকের উপরে 1 টি বাইট বাফার তৈরি করে, চরিত্রটিকে এতে রাখে এবং লেখার জন্য এই বাফারটি দেয়। সুতরাং, char সংস্করণটি কিছুটা ধীর।






string-literals