সি ++ তে, আমি যা খাচ্ছি না তার জন্য আমি কি অর্থ প্রদান করছি?


170

আসুন সি এবং সি ++ এ নিম্নলিখিত হ্যালো বিশ্বের উদাহরণগুলি বিবেচনা করুন:

main.c

#include <stdio.h>

int main()
{
    printf("Hello world\n");
    return 0;
}

main.cpp

#include <iostream>

int main()
{
    std::cout<<"Hello world"<<std::endl;
    return 0;
}

আমি যখন এগুলি সমাবেশে গডবোল্টে সংকলন করি তখন সি কোডের আকার মাত্র 9 টি লাইন ( gcc -O3) থাকে:

.LC0:
        .string "Hello world"
main:
        sub     rsp, 8
        mov     edi, OFFSET FLAT:.LC0
        call    puts
        xor     eax, eax
        add     rsp, 8
        ret

তবে সি ++ কোডের আকার 22 টি লাইন ( g++ -O3):

.LC0:
        .string "Hello world"
main:
        sub     rsp, 8
        mov     edx, 11
        mov     esi, OFFSET FLAT:.LC0
        mov     edi, OFFSET FLAT:_ZSt4cout
        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)
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
        xor     eax, eax
        add     rsp, 8
        ret
_GLOBAL__sub_I_main:
        sub     rsp, 8
        mov     edi, OFFSET FLAT:_ZStL8__ioinit
        call    std::ios_base::Init::Init() [complete object constructor]
        mov     edx, OFFSET FLAT:__dso_handle
        mov     esi, OFFSET FLAT:_ZStL8__ioinit
        mov     edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
        add     rsp, 8
        jmp     __cxa_atexit

... যা অনেক বড়।

এটি বিখ্যাত যে সি ++ এ আপনি যা খান তার জন্য অর্থ প্রদান করেন। সুতরাং, এই ক্ষেত্রে, আমি কি জন্য অর্থ প্রদান করছি?


3
মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
স্যামুয়েল লিউ


26
eatসি ++ এর সাথে যুক্ত শব্দটি কখনও শুনেনি । আমি বিশ্বাস করি যে আপনি বলতে চাইছেন: "আপনি কেবল তার ব্যবহারের জন্য অর্থ প্রদান করেন "?
গিয়াকোমো আলজেটা

7
@ জিয়াকোমো অলজিটা, ... এটি একটি চালচলন, যা আপনি খেতে পারেন এমন সমস্ত বুফে ধারণাটি প্রয়োগ করে। আরও সুনির্দিষ্ট শব্দটি ব্যবহার করা অবশ্যই বিশ্বব্যাপী দর্শকদের কাছে পছন্দনীয়, তবে স্থানীয় আমেরিকান ইংলিশ স্পিকার হিসাবে এই শিরোনামটি আমার কাছে অর্থবোধ করে।
চার্লস ডাফি

5
@ ট্রলি 813 মেমরি ফাঁসের উদ্ধৃতি এবং ওপি প্রশ্নের সাথে কোনও সম্পর্ক নেই। "আপনি কেবল যা ব্যবহার করেন তার জন্য" আপনি অর্থ প্রদান করেন "/" আপনি যা ব্যবহার করেন না তার জন্য আপনি অর্থ প্রদান করেন না "এর বক্তব্যটি আপনি যদি নির্দিষ্ট বৈশিষ্ট্য / বিমূর্ততা ব্যবহার না করেন তবে কোনও পারফরম্যান্স হিট নেওয়া হয় না। মেমরি ফুটো এর সাথে মোটেই কিছু করার নেই এবং এটি কেবল দেখায় যে শব্দটি eatআরও অস্পষ্ট এবং এড়ানো উচিত।
গিয়াকোমো আলজেটা

উত্তর:


60

আপনি যা প্রদান করছেন তা হ'ল ভারী গ্রন্থাগার কল করা (কনসোলে মুদ্রণের মতো ভারী নয়)। আপনি একটি ostreamবস্তু সূচনা । কিছু লুকানো স্টোরেজ আছে। তারপরে, আপনি কল করেন std::endlযা এর প্রতিশব্দ নয় \n। দ্যiostreamআপনার লাইব্রেরি অনেক সেটিংস সামঞ্জস্য এবং প্রোগ্রামার বদলে প্রসেসর উপর বোঝা নির্বাণ সাহায্য করে। এই জন্য আপনি কি প্রদান করা হয়।

কোডটি পর্যালোচনা করুন:

.LC0:
        .string "Hello world"
main:

একটি অস্ট্রিমা অবজেক্ট + কাউট শুরু করা হচ্ছে

    sub     rsp, 8
    mov     edx, 11
    mov     esi, OFFSET FLAT:.LC0
    mov     edi, OFFSET FLAT:_ZSt4cout
    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)

coutনতুন লাইন প্রিন্ট করতে আবার কল করা এবং ফ্লাশ করা

    mov     edi, OFFSET FLAT:_ZSt4cout
    call    std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
    xor     eax, eax
    add     rsp, 8
    ret

স্ট্যাটিক স্টোরেজ আরম্ভ:

_GLOBAL__sub_I_main:
        sub     rsp, 8
        mov     edi, OFFSET FLAT:_ZStL8__ioinit
        call    std::ios_base::Init::Init() [complete object constructor]
        mov     edx, OFFSET FLAT:__dso_handle
        mov     esi, OFFSET FLAT:_ZStL8__ioinit
        mov     edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
        add     rsp, 8
        jmp     __cxa_atexit

এছাড়াও, ভাষা এবং গ্রন্থাগারের মধ্যে পার্থক্য করা অপরিহার্য।

বিটিডাব্লু, এটি গল্পের একটি অংশ মাত্র। আপনি যে ফাংশনগুলিতে কল করছেন তাতে কী লেখা আছে তা আপনি জানেন না।


5
অতিরিক্ত নোট হিসাবে, পুরো পরীক্ষায় দেখা যাবে যে "ios_base :: sync_with_stdio (মিথ্যা)" দিয়ে একটি সি ++ প্রোগ্রাম প্রিপেন্ডিং; এবং "cin.tie (NULL)" প্রিন্টফের চেয়ে কাউট দ্রুত তৈরি করবে (প্রিন্টফের ফর্ম্যাট ওভারহেডের ফর্ম্যাট রয়েছে)। যথাযথভাবে cout; printf; coutলেখার বিষয়টি নিশ্চিত করা থেকে ওভারহেডকে সরিয়ে দেয় (যেহেতু তাদের নিজস্ব বাফার রয়েছে)। দ্বিতীয়টি অদৃশ্য হয়ে যাবে coutএবং এর cinফলে cout; cinব্যবহারকারীকে প্রথমে তথ্যের জন্য জিজ্ঞাসা করতে পারে। ফ্লাশিং কেবল তখনই সিঙ্ক করতে বাধ্য করবে যখন আপনার আসলে এটির প্রয়োজন হবে।
নিকোলাস পিপিটোন

হাই নিকোলাস, এই দরকারী নোটগুলি যুক্ত করার জন্য আপনাকে অনেক ধন্যবাদ।
আরশ

"ভাষা এবং গ্রন্থাগারের মধ্যে পার্থক্য করা অপরিহার্য": হ্যাঁ হ্যাঁ, তবে একটি ভাষা নিয়ে আসা স্ট্যান্ডার্ড লাইব্রেরি সর্বত্রই একমাত্র উপলভ্য, তাই এটি সর্বত্র ব্যবহৃত হচ্ছে (এবং হ্যাঁ, সি স্ট্যান্ডার্ড লাইব্রেরিটি অংশ সি ++ নির্দিষ্টকরণের, যাতে এটি যখন ইচ্ছা তখন ব্যবহার করা যায়)। "আপনি যে ফাংশনগুলিতে কল করছেন তাতে কী লেখা আছে তা আপনি জানেন না": আপনি যদি সত্যিই জানতে চান তবে আপনি স্ট্যাটিকালি লিঙ্ক করতে পারেন, এবং আপনি যে কলিং কোডটি পরীক্ষা করেছেন তা সম্ভবত অপ্রাসঙ্গিক।
পিটার - মনিকা পুনরায় ইনস্টল করুন

211

সুতরাং, এই ক্ষেত্রে, আমি কি জন্য অর্থ প্রদান করছি?

std::cout এর চেয়ে বেশি শক্তিশালী এবং জটিল printf । এটি লোকেল, রাষ্ট্রীয় ফর্ম্যাটিং ফ্ল্যাগ এবং আরও অনেক কিছুকে সমর্থন করে।

আপনার যদি সেগুলির দরকার না হয় তবে ব্যবহার করুন std::printfবা std::puts- এগুলি উপলব্ধ <cstdio>


এটি বিখ্যাত যে সি ++ এ আপনি যা খান তার জন্য অর্থ প্রদান করেন।

আমি এটি পরিষ্কারও করতে চাই যে সি ++ ! = সি ++ স্ট্যান্ডার্ড লাইব্রেরি। স্ট্যান্ডার্ড লাইব্রেরিটি সাধারণ উদ্দেশ্যে এবং "দ্রুত যথেষ্ট" হওয়ার কথা বলে মনে করা হয়, তবে এটি আপনার যা প্রয়োজন তার একটি বিশেষায়িত প্রয়োগের চেয়ে ধীর হবে।

অন্যদিকে, সি ++ ভাষা অপ্রয়োজনীয় অতিরিক্ত লুকানো ব্যয় (উদাহরণস্বরূপ অপ্ট-ইন virtual, কোনও আবর্জনা সংগ্রহ না করে) কোড লেখার পক্ষে এটি সম্ভব করার চেষ্টা করে ।


4
বলার অপেক্ষা রাখে না জন্য +1 স্ট্যান্ডার্ড লাইব্রেরী সাধারণ এবং "যথেষ্ট দ্রুত" হতে অনুমিত হয়, কিন্তু এটা প্রায়ই আপনার যা প্রয়োজন একটি বিশেষ বাস্তবায়ন তুলনায় ধীর হবে। অনেকগুলি নিজেরাই ঘূর্ণায়মান বনাম পারফরম্যান্সের প্রভাবগুলি বিবেচনা না করে অন্ধভাবে এসটিএল উপাদানগুলি ব্যবহার করছে বলে মনে হয়।
ক্রেগ এস্টে

7
@ ক্রেইগ ওটিওএইচ স্ট্যান্ডার্ড লাইব্রেরির অনেকগুলি অংশ সাধারণত সাধারণত পরিবর্তে যেটি উত্পাদন করতে পারে তার চেয়ে দ্রুত এবং আরও সঠিক হয়।
পিটার - মনিকা পুনরায় ইনস্টল করুন

2
@ পিটারএ.স্নাইডার ওটিওএইচ, যখন এসটিএল সংস্করণটি 20x-30x ধীর গতির হয়, আপনার নিজের ঘূর্ণায়মান ভাল জিনিস। আমার উত্তরটি এখানে দেখুন: কোডরেভিউ.স্ট্যাকেক্সেঞ্জারওয়েজ / সেকশনস / ১৯১7477/২ এর মধ্যে, অন্যরাও [কমপক্ষে একটি আংশিক] নিজের রোল দেওয়ার পরামর্শ দিয়েছে।
ক্রেগ Estey

1
@ ক্রেইগস্টেটি একজন ভেক্টর হ'ল (প্রাথমিক গতিশীল বরাদ্দ বাদে যা উল্লেখযোগ্য হতে পারে, একটি নির্দিষ্ট উদাহরণ দিয়ে শেষ পর্যন্ত কতটা কাজ করা হবে তার উপর নির্ভর করে) সি অ্যারের চেয়ে কম দক্ষ নয়; এটি না ডিজাইন করা হয়েছে। এটিকে চারপাশে অনুলিপি না করা, প্রাথমিক পর্যায়ে পর্যাপ্ত স্থান সংরক্ষণ করা ইত্যাদি যত্ন নিতে হবে তবে এটি অবশ্যই অ্যারে দিয়ে করা উচিত এবং কম নিরাপদে। আপনার লিঙ্কযুক্ত উদাহরণের প্রতি শ্রদ্ধা সহ: হ্যাঁ, ভেক্টরগুলির একটি ভেক্টর 2D অ্যারের তুলনায় অতিরিক্ত ইন্ডাইরেশন বহন করবে, তবে আমি ধরে নিচ্ছি যে 20x দক্ষতা সেখানে নেই তবে অ্যালগরিদমে রয়েছে।
পিটার - মনিকা

174

আপনি সি এবং সি ++ এর তুলনা করছেন না। আপনি তুলনা করছেন printfএবংstd::cout , যা বিভিন্ন জিনিস (লোকেলস, ​​রাষ্ট্রীয় বিন্যাস ইত্যাদি) সক্ষম of

তুলনার জন্য নিম্নলিখিত কোড ব্যবহার করার চেষ্টা করুন। গডবোল্ট উভয় ফাইলের জন্য একই সমাবেশ উত্পন্ন করে (জিসিসি 8.2, -O3 দিয়ে পরীক্ষিত)।

main.c:

#include <stdio.h>

int main()
{
    int arr[6] = {1, 2, 3, 4, 5, 6};
    for (int i = 0; i < 6; ++i)
    {
        printf("%d\n", arr[i]);
    }
    return 0;
}

main.cpp:

#include <array>
#include <cstdio>

int main()
{
    std::array<int, 6> arr {1, 2, 3, 4, 5, 6};
    for (auto x : arr)
    {
        std::printf("%d\n", x);
    }
}


সমমানের কোড দেখানোর এবং কারণ ব্যাখ্যা করার জন্য চিয়ার্স।
হ্যাকস্ল্যাশ

134

আপনার তালিকাগুলি সত্যিই আপেল এবং কমলা তুলনা করছে, তবে বেশিরভাগ অন্যান্য উত্তরে অন্তর্নিহিত কারণে নয়।

আসুন আপনার কোডটি আসলে কী তা পরীক্ষা করে দেখুন:

সি:

  • একটি একক স্ট্রিং মুদ্রণ করুন, "Hello world\n"

সি ++:

  • স্ট্রিং স্ট্রিম "Hello world"মধ্যেstd::cout
  • std::endlম্যানিপুলেটারটি স্ট্রিম করুনstd::cout

স্পষ্টতই আপনার সি ++ কোড দ্বিগুণ কাজ করছে। ন্যায্য তুলনার জন্য আমাদের এটি একত্রিত করা উচিত:

#include <iostream>

int main()
{
    std::cout<<"Hello world\n";
    return 0;
}

… এবং হঠাৎ আপনার এসেম্বলি কোডটি mainসি এর সাথে খুব মিল দেখাচ্ছে:

main:
        sub     rsp, 8
        mov     esi, OFFSET FLAT:.LC0
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
        xor     eax, eax
        add     rsp, 8
        ret

প্রকৃতপক্ষে, আমরা সি এবং সি ++ কোড লাইনটি লাইন দ্বারা তুলনা করতে পারি এবং খুব কম পার্থক্য রয়েছে :

sub     rsp, 8                      sub     rsp, 8
mov     edi, OFFSET FLAT:.LC0   |   mov     esi, OFFSET FLAT:.LC0
                                >   mov     edi, OFFSET FLAT:_ZSt4cout
call    puts                    |   call    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
xor     eax, eax                    xor     eax, eax
add     rsp, 8                      add     rsp, 8
ret                                 ret

কেবল আসল পার্থক্যটি হ'ল সি ++ এ আমরা operator <<দুটি আর্গুমেন্ট ( std::coutএবং স্ট্রিং) দিয়ে কল করি । কাছাকাছি সি একিভ্যালেন্ট ব্যবহার করে আমরা সেই সামান্যতম পার্থক্যটিও সরিয়ে ফেলতে পারি: fprintfযার স্ট্রিমটি নির্দিষ্ট করে এমন প্রথম যুক্তিও রয়েছে।

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

তবে, অন্যান্য উত্তরে বর্ণিত হিসাবে, এই দুটি প্রোগ্রামের মধ্যে প্রাসঙ্গিক পার্থক্য mainফাংশনের সমাবেশের আউটপুটে পাওয়া যাবে না কারণ পর্দার আড়ালে সমস্ত ভারী উত্তোলন ঘটে happens


21
উল্লেখ্য সি রানটাইম এছাড়াও সেট আপ করা প্রয়োজন, এবং এই একটি ফাংশন বলা ঘটবে _startকিন্তু এটির কোড সি রানটাইম লাইব্রেরির অংশ। যে কোনও হারে এটি সি এবং সি ++ উভয়ের জন্যই ঘটে।
কনরাড রুডল্ফ

2
@Deduplicator: বাস্তবিক, ডিফল্টরূপে iostream গ্রন্থাগার করে না কোন এর বাফারিং std::coutএর পরিবর্তে ইনপুট / আউটপুট stdio বাস্তবায়নে (যা তার নিজস্ব বাফার উপলব্ধ মেকানিজম ব্যবহার করে) প্রেরণ করা হয়। বিশেষত, যখন একটি ইন্টারেক্টিভ টার্মিনালের সাথে সংযুক্ত থাকে (তখন যা পরিচিত হয়) তখন ডিফল্টরূপে আপনি কখন লেখার সময় পুরোপুরি বাফার আউটপুট দেখতে পাবেন না std::cout। আপনি যদি আইস্ট্রিম লাইব্রেরিটির নিজস্ব বাফারিং ব্যবস্থা ব্যবহার করতে চান তবে আপনাকে স্পষ্টতই স্টডিওর সাথে সিঙ্ক্রোনাইজেশন অক্ষম করতে হবে std::cout

6
@ কনরাড রুডল্ফ: আসলে printfএখানে স্ট্রিমগুলি প্রবাহিত করার দরকার নেই। আসলে, একটি সাধারণ ব্যবহারের ক্ষেত্রে (আউটপুট ফাইলে পুনঃনির্দেশিত), আপনি সাধারণত দেখতে পাবেন যে printfবিবৃতিটি ফ্লাশ হয় না । কেবলমাত্র যখন আউটপুট লাইন-বাফার বা আনফারড করা হয় তখনই এটি ফ্লাশটিকে printfট্রিগার করবে ।

2
@ পিটারকার্ডস: ঠিক আছে, আপনি ফলস্বরূপ আউটপুট বাফার দিয়ে ব্লক করতে পারবেন না, তবে আপনি যে আশ্চর্যরূপে প্রোগ্রামটি আপনার ইনপুটটি গ্রহণ করেছেন এবং প্রত্যাশিত আউটপুট প্রদর্শন না করে মার্চ চালিয়ে যেতে পারেন তা অবাক করে দিতে পারেন। আমি এটি জানি কারণ আমি একটি "সাহায্যটি ডিবাগ করার উপলক্ষ পেয়েছিলাম, ইনপুট চলাকালীন আমার প্রোগ্রামটি ঝুলছে তবে কেন আমি তা বুঝতে পারি না!" যা অন্য বিকাশকারীকে কয়েক দিনের জন্য ফিট করে।

2
@ পিটারকর্ডস: আমি যে যুক্তিটি দিচ্ছি তা হ'ল "আপনার অর্থ কী লিখুন" - আউটপুট অবিলম্বে উপলব্ধ হওয়ার জন্য যখন আপনি বোঝাচ্ছেন তখন নিউলাইনগুলি উপযুক্ত এবং যখন আউটপুট অবিলম্বে উপলব্ধ হওয়ার জন্য আপনি বোঝাতে চাইছেন তখন এনডেল উপযুক্ত appropriate

53

এটি বিখ্যাত যে সি ++ এ আপনি যা খান তার জন্য অর্থ প্রদান করেন। সুতরাং, এই ক্ষেত্রে, আমি কি জন্য অর্থ প্রদান করছি?

এটা সহজ। আপনি এর জন্য অর্থ প্রদান std::cout। "আপনি যা খান কেবল তার জন্য আপনি অর্থ প্রদান করেন" এর অর্থ এই নয় যে "আপনি সর্বদা সেরা দাম পান"। অবশ্যই, printfসস্তা। যে std::coutকেউ নিরাপদে এবং আরও বহুমুখী তর্ক করতে পারে , সুতরাং এর বৃহত্তর ব্যয়কে ন্যায়সঙ্গত করা হয় (এটির জন্য আরও বেশি ব্যয় হয় তবে আরও মান সরবরাহ করা হয়), তবে এটি বিন্দুটি মিস করে না। আপনি ব্যবহার করেন না printf, আপনি ব্যবহার করেন std::cout, তাই আপনি ব্যবহারের জন্য অর্থ প্রদান করেন std::cout। আপনি ব্যবহারের জন্য অর্থ প্রদান করবেন না printf

একটি ভাল উদাহরণ ভার্চুয়াল ফাংশন। ভার্চুয়াল ফাংশন কিছু রানটাইম খরচ এবং স্থান প্রয়োজনীয়তা আছে - কিন্তু শুধুমাত্র যদি আপনি আসলে তাদেরকে ব্যবহার করো। যদি আপনি ভার্চুয়াল ফাংশন ব্যবহার না করেন তবে আপনি কোনও মূল্য দিবেন না।

কয়েকটি মন্তব্য

  1. এমনকি সি ++ কোড আরও সমাবেশ নির্দেশাবলীর জন্য মূল্যায়ন করলেও এটি এখনও কয়েকটি মুখ্য নির্দেশাবলী এবং কোনও কার্য সম্পাদনের ওভারহেড সম্ভবত বাস্তব I / O ক্রিয়াকলাপ দ্বারা বামনযুক্ত।

  2. প্রকৃতপক্ষে, কখনও কখনও এটি "খাওয়া খাওয়ার জন্য আপনি সি ++ প্রদান করেন" এর চেয়েও ভাল। উদাহরণস্বরূপ, সংকলক কিছু পরিস্থিতিতে সেই ভার্চুয়াল ফাংশন কলটির প্রয়োজন হয় না এবং এটি অ-ভার্চুয়াল কলটিতে রূপান্তর করতে পারে। এর অর্থ আপনি বিনামূল্যে ভার্চুয়াল ফাংশন পেতে পারেন । কি দুর্দান্ত না?


6
আপনি বিনামূল্যে ভার্চুয়াল ফাংশন পাবেন না। আপনাকে প্রথমে সেগুলি লেখার জন্য আপনাকে এখনও মূল্য দিতে হবে এবং তারপরে আপনার কোডটির সংকলকটির রূপান্তরটি ডিবাগ করতে হবে যখন এটি করা উচিত বলে আপনার ধারণার সাথে মেলে না।
আলেফজেরো

2
@ এলফজারো আমি নিশ্চিত না যে এটি পারফরম্যান্স ব্যয়ের সাথে উন্নয়ন ব্যয়ের তুলনা করতে বিশেষভাবে প্রাসঙ্গিক।

পাংয়ের জন্য এমন দুর্দান্ত সুযোগটি নষ্ট হয় ... আপনি 'দামের' পরিবর্তে 'ক্যালোরি' শব্দটি ব্যবহার করতে পারেন। সেখান থেকে আপনি বলতে পারেন যে সি ++ সি এর চেয়ে মোটা Or বা কমপক্ষে ... নির্দিষ্ট কোডটি (আমি সি এর পক্ষে পক্ষপাতদুষ্ট সি এর পক্ষে, তাই আমি মোটামুটি ছাড়িয়ে যেতে পারি না)। হায়রে। @ বিলকোকুয়া এটি সমস্ত ক্ষেত্রে প্রাসঙ্গিক নাও হতে পারে তবে এটি অবশ্যই অবহেলা করা উচিত নয়। সুতরাং এটি সম্পূর্ণ প্রাসঙ্গিক।
Pryftan

46

"প্রিন্টফের জন্য সমাবেশের তালিকা" প্রিন্টফের জন্য নয়, তবে পুটসের জন্য (কম্পাইলার অপ্টিমাইজেশনের ধরণের?); প্রিন্টফ প্রেটির চেয়ে অনেক বেশি জটিল ... ভুলে যাবেন না!


13
এটি এখনও অবধি সেরা উত্তর, যেহেতু অন্যরা সমস্তই std::coutঅভ্যন্তরীণ অভ্যন্তরীণ বিষয়ে একটি লাল রঙের হেরিংয়ের সাথে ঝুলিয়ে রাখে , যা সমাবেশের তালিকাতে দৃশ্যমান নয়।
কনরাড রুডলফ

12
অ্যাসেম্বলি তালিকা কোনও কলটির জন্য puts যা printfআপনি কেবল একটি একক বিন্যাসের স্ট্রিং এবং শূন্য অতিরিক্ত আরগগুলি পাস করলে কলটির অনুরূপ । ( xor %eax,%eaxব্যাতিক্রমী ফাংশনগুলিতে নিবন্ধগুলিতে আমরা শূন্য এফপি আরোগুলি পাস করছি কারণ এগুলি ব্যতীত)) এর মধ্যে দুটিই বাস্তবায়ন নয়, কেবল লাইব্রেরি ফাংশনে একটি পয়েন্টার দিয়ে যাচ্ছে। তবে হ্যাঁ, জিসিসি- printfতে putsকেবল এমন কিছু ফর্ম্যাটগুলির জন্য উপযুক্ত যা কেবল আছে "%s", বা যখন কোনও রূপান্তর হয় না এবং স্ট্রিংটি একটি নতুন লাইনের সাথে শেষ হয়।
পিটার কর্ডস

45

আমি এখানে কিছু বৈধ উত্তর দেখতে পাচ্ছি, তবে আমি বিশদটিতে আরও কিছুটা পেতে চলেছি।

আপনি যদি পাঠ্যের এই পুরো প্রাচীরটি দিয়ে যেতে না চান তবে আপনার মূল প্রশ্নের উত্তরের জন্য নীচের সারসংক্ষেপে ঝাঁপুন।


বিমূর্তন

সুতরাং, এই ক্ষেত্রে, আমি কি জন্য অর্থ প্রদান করছি?

আপনি বিমূর্তনের জন্য অর্থ প্রদান করছেন । সহজ এবং আরও বেশি মানব বান্ধব কোড লিখতে সক্ষম হওয়ায় ব্যয় হয়। সি ++ এ, যা একটি অবজেক্ট-ওরিয়েন্টেড ভাষা, প্রায় প্রতিটি জিনিসই একটি বস্তু an আপনি যখন কোনও বস্তু ব্যবহার করেন, তখন তিনটি প্রধান জিনিস সর্বদা হুডের নীচে ঘটবে:

  1. অবজেক্ট তৈরি, অবজেক্টটি নিজে এবং তার ডেটার জন্য মেমরির বরাদ্দ।
  2. অবজেক্ট ইনিশিয়ালেশন (সাধারণত কিছু init()পদ্ধতির মাধ্যমে )। সাধারণত এই পদক্ষেপের প্রথম জিনিস হিসাবে হুডের নীচে মেমরি বরাদ্দ ঘটে।
  3. অবজেক্ট ধ্বংস (সর্বদা নয়)।

আপনি কোডটিতে এটি দেখতে পাচ্ছেন না, তবে প্রতিবার একবার আপনি যখন কোনও বস্তু ব্যবহার করেন উপরের তিনটি জিনিসকে কোনও না কোনওভাবে ঘটতে হবে। আপনি যদি ম্যানুয়ালি সবকিছুই করেন তবে কোড অবশ্যই স্পষ্টভাবে দীর্ঘতর হবে।

এখন, অ্যাডস্ট্রাকশন ওভারহেড যোগ না করে দক্ষতার সাথে তৈরি করা যেতে পারে: পদ্ধতি ইনলাইনিং এবং অন্যান্য কৌশলগুলি সংযোজক এবং প্রোগ্রামার উভয়ই বিমূর্তির ওভারহেডগুলি সরাতে ব্যবহার করতে পারেন, তবে এটি আপনার ক্ষেত্রে নয়।

সত্যিই কি ঘটছে সি ++ এ?

এটি এখানে, ভেঙে দেওয়া:

  1. std::ios_baseবর্গ সক্রিয়া করা হয়, যা সবকিছু আমি / এর সাথে সম্পর্কিত হে জন্য বেস বর্গ।
  2. std::coutবস্তুর সক্রিয়া করা হয়।
  3. আপনার স্ট্রিংটি লোড করা হয়েছে এবং এতে পাস করা হয়েছে std::__ostream_insert, যা (আপনি ইতিমধ্যে নামটি আবিষ্কার করেছেন) একটি পদ্ধতি std::cout(মূলত <<অপারেটর) যা স্ট্রিমটিতে একটি স্ট্রিং যুক্ত করে।
  4. cout::endlএছাড়াও পাস করা হয় std::__ostream_insert
  5. __std_dso_handleএ পাস করা হয় __cxa_atexit, যা একটি বিশ্বব্যাপী ফাংশন যা প্রোগ্রামটি ছাড়ার আগে "পরিষ্কার" করার জন্য দায়বদ্ধ। __std_dso_handleএই বিশ্বব্যাপী অবজেক্টগুলি ধ্বংস করতে এবং ধ্বংস করতে নিজেই এই ফাংশনটি বলে।

সুতরাং C == ব্যবহার করে কোনও কিছুর জন্য অর্থ প্রদান করছেন না?

সি কোডে খুব কম পদক্ষেপই ঘটছে:

  1. আপনার স্ট্রিং লোড করা হয়েছে এবং রেজিস্টার putsমাধ্যমে পাস edi
  2. puts ডাকা হয়।

কোথাও কোনও অবজেক্ট নেই, তাই কোনও কিছু আরম্ভ / ধ্বংস করার দরকার নেই।

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

আপনি যদি এই প্রোগ্রামটি খাঁটি সমাবেশে লিখেন তবে এটি দেখতে এরকম কিছু দেখাবে:

jmp start

msg db "Hello world\n"

start:
    mov rdi, 1
    mov rsi, offset msg
    mov rdx, 11
    mov rax, 1          ; write
    syscall
    xor rdi, rdi
    mov rax, 60         ; exit
    syscall

কোনটি invoking মধ্যে মূলত শুধুমাত্র ফলাফল write প্রাপ্ত syscall দ্বারা অনুসরণ exitপ্রাপ্ত syscall। এখন এই ন্যূনতমরূপে একই জিনিস সাধা হবে।


সংক্ষেপ

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

আপনার মূল প্রশ্নের উত্তর :

আমি যা খাচ্ছি না তার জন্য আমি কি অর্থ দিচ্ছি?

এই নির্দিষ্ট ক্ষেত্রে, হ্যাঁ । আপনি সি -++ এর চেয়ে বেশি সি-এর চেয়ে বেশি যে কোনও অফার দিচ্ছেন না সেটির সুবিধা নিচ্ছেন না, তবে এটি কেবল কারণ এই সহজ কোডের কিছু নেই যা সি ++ আপনাকে সহায়তা করতে পারে: এটি এতই সহজ যে আপনার সত্যিকার অর্থেই সি ++ লাগবে না।


ওহ, এবং আরও একটি জিনিস!

সি ++ এর সুবিধাগুলি প্রথম নজরে সুস্পষ্ট নাও লাগতে পারে, যেহেতু আপনি খুব সাধারণ এবং ছোট প্রোগ্রাম লিখেছেন তবে কিছুটা জটিল উদাহরণ দেখুন এবং পার্থক্যটি দেখুন (উভয় প্রোগ্রামই হুবহু একই কাজ করে):

সি :

#include <stdio.h>
#include <stdlib.h>

int cmp(const void *a, const void *b) {
    return *(int*)a - *(int*)b;
}

int main(void) {
    int i, n, *arr;

    printf("How many integers do you want to input? ");
    scanf("%d", &n);

    arr = malloc(sizeof(int) * n);

    for (i = 0; i < n; i++) {
        printf("Index %d: ", i);
        scanf("%d", &arr[i]);
    }

    qsort(arr, n, sizeof(int), cmp)

    puts("Here are your numbers, ordered:");

    for (i = 0; i < n; i++)
        printf("%d\n", arr[i]);

    free(arr);

    return 0;
}

সি ++ :

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main(void) {
    int n;

    cout << "How many integers do you want to input? ";
    cin >> n;

    vector<int> vec(n);

    for (int i = 0; i < vec.size(); i++) {
        cout << "Index " << i << ": ";
        cin >> vec[i];
    }

    sort(vec.begin(), vec.end());

    cout << "Here are your numbers:" << endl;

    for (int item : vec)
        cout << item << endl;

    return 0;
}

আশা করি আপনি এখানে আমার অর্থ কী তা পরিষ্কার করে দেখতে পারবেন। সিটিতে কীভাবে আপনাকে নিম্ন স্তরে মেমরি পরিচালনা করতে হবে mallocএবং freeকীভাবে আপনাকে সূচীকরণ এবং আকারগুলি সম্পর্কে আরও যত্নবান হতে হবে এবং ইনপুট এবং প্রিন্টিংয়ের সময় কীভাবে আপনাকে খুব সুনির্দিষ্ট হতে হবে তা লক্ষ করুন ।


27

শুরু করার জন্য কয়েকটি ভুল ধারণা রয়েছে। প্রথমত, সি ++ প্রোগ্রামটি 22 টি নির্দেশাবলীতে ফল দেয় না , এটি 22 টির মতোই রয়েছে (আমি আমার সংখ্যাটি টুপি থেকে টানলাম, তবে এটি প্রায় ব্যালপার্কে)। এছাড়াও, সি কোড 9 টি নির্দেশের ফলাফল দেয় না । সেগুলি কেবলমাত্র আপনিই দেখেন।

সি কোডটি যা করে তা হ'ল, আপনি দেখতে পাচ্ছেন না এমন অনেকগুলি স্টাফ করার পরে, এটি সিআরটি থেকে একটি ফাংশন কল করে (যা সাধারণত তবে অংশীদারি হিসাবে প্রকাশিত হয় না ), তারপরে রিটার্নের মান বা হ্যান্ডেলটি পরীক্ষা করে না ত্রুটি, এবং জামিন আউট। সংকলক এবং অপ্টিমাইজেশন সেটিংসের উপর নির্ভর করে এটি এমনকি সত্যই কল করে না printfতবে puts, বা আরও কিছু আদিম।
আপনি আরও + কম একই প্রোগ্রামটি লিখতে পারতেন (কিছু অদৃশ্য init ফাংশন ব্যতীত) পাশাপাশি C ++ তে, কেবল যদি আপনি একই ফাংশনটিকে একইভাবে ডাকতেন। অথবা, আপনি যদি অতি-সঠিক হতে চান, তবে একই ফাংশনটি উপসর্গযুক্ত std::

সংশ্লিষ্ট সি ++ কোড বাস্তবে একই জিনিস নয়। যদিও <iostream>এটির পুরো অংশটি একটি চর্বিযুক্ত কুরুচিপূর্ণ শূকর হিসাবে সুপরিচিত যা ছোট প্রোগ্রামগুলির জন্য একটি প্রচুর ওভারহেড যুক্ত করে (একটি "বাস্তব" প্রোগ্রামে আপনি সত্যিই এতটা লক্ষ্য করেন না), কিছুটা সুন্দর ব্যাখ্যাটি হ'ল এটি একটি ভয়াবহ কাজ করে আপনি দেখতে পাচ্ছেন না এবং যা ঠিক কাজ করে তা প্রচুর পরিমাণে । বিভিন্ন সংখ্যক ফর্ম্যাট এবং লোকেল এবং হোয়াট নোট, এবং বাফারিং এবং সঠিক ত্রুটি-পরিচালনা সহ মোটামুটি কোনও হাফজার্ড স্টাফের যাদুকরী বিন্যাসে অন্তর্ভুক্ত তবে সীমাবদ্ধ নয়। ত্রুটি পরিচালনা? হ্যাঁ, অনুমান করুন, স্ট্রিং আউটপুট করা আসলে ব্যর্থ হতে পারে, এবং সি প্রোগ্রামের বিপরীতে, সি ++ প্রোগ্রাম এটিকে নিঃশব্দে উপেক্ষা করবে না । কি বিবেচনাstd::ostreamহুডের নীচে কাজ করে এবং কারও সম্পর্কে অবহিত না হয়ে এটি আসলে বেশ হালকা ওজনের। আমি এটি ব্যবহার করছি না এর মতো নয় কারণ আমি আবেগের সাথে স্ট্রিম সিনট্যাক্সটিকে ঘৃণা করি। তবে তবুও, আপনি এটি কী করে তা বিবেচনা করলে এটি দুর্দান্ত pretty

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

যদি, সি-কোড লেখার জন্য সেরা-আগুন-এবং-ভুলে যাওয়া-আশা-পরিবর্তে আপনি সঠিকভাবে যত্নবান হন যা সঠিক (যেমন আপনি আসলে ত্রুটিগুলি পরীক্ষা করে দেখেন, এবং প্রোগ্রামটি ত্রুটির উপস্থিতিতে সঠিকভাবে আচরণ করে) তবে পার্থক্যটি প্রান্তিক, যদি বিদ্যমান থাকে


16
খুব ভাল উত্তর, এই জবাব ব্যতীত: "তবে নিশ্চিত, সি ++ সামগ্রিকভাবে সি হিসাবে কার্যকর হতে পারে না" কেবল ভুল। সি ++ সি এর মতো দক্ষ হতে পারে এবং সমপরিমাণ সি কোডের তুলনায় পর্যাপ্ত উচ্চ-স্তরের কোড আরও দক্ষ হতে পারে । হ্যাঁ, ব্যতিক্রমগুলি পরিচালনা করার কারণে সি ++ এর কিছু ওভারহেড রয়েছে তবে আধুনিক সংকলকগুলিতে ভাল ব্যয়-মুক্ত বিমূর্ততা থেকে সম্পাদিত পারফরম্যান্স লাভের তুলনায় এর ওভারহেড উপেক্ষিত।
কনরাড রুডল্ফ

আমি যদি সঠিকভাবে বুঝতে পারি, তবে কি std::coutব্যতিক্রমগুলি ছুঁড়ে দেওয়া হবে?
সাহের

6
@ সাহের: হ্যাঁ, না, সম্ভবত std::coutএটি হ'ল একটি std::basic_ostreamএবং এটি নিক্ষেপ করতে পারে এবং এটির জন্য কনফিগার করা থাকলে বা এটি ব্যতিক্রমগুলি গ্রাস করতে পারে তবে তা ঘটতে পারে না- কথাটি হ'ল, স্টাফ ব্যর্থ হতে পারে এবং সি ++ পাশাপাশি সি ++ স্ট্যান্ডার্ড লিব (বেশিরভাগ) নির্মিত তাই ব্যর্থতা সহজেই নজরে না যায়। এটি বিরক্তি এবং আশীর্বাদ (তবে বিরক্তির চেয়ে আশীর্বাদ)। অন্যদিকে সি কেবল আপনাকে মাঝের আঙুলটি দেখায়। আপনি কোনও রিটার্ন কোড চেক করেন না, কী হয়েছে তা আপনি কখনই জানেন না।
দামন

1
@ কনরাডরুডল্ফ: সত্য, আমি এই বিষয়টির সাথে উল্লেখ করার চেষ্টা করছিলাম "আমি সি ++ এর চেয়ে ভাল পারফর্মেন্স খুব কমই পাইনি কারণ একটি কারণ বা অন্য কারণে এটি আরও অনুকূল অনুকূলকরণের জন্য ধার দেয় বলে মনে হয়। বিশেষত কেন আমাকে জিজ্ঞাসা করবেন না" । এটি কেন তাত্ক্ষণিকভাবে সুস্পষ্ট নয়, তবে খুব কমই এটি কেবল আরও ভালরূপে অনুকূল হয়। যে কারনেই হোক. আপনি ভাববেন যে এটি সবই অপটিমাইজারের মতো,
দামন

22

আপনি একটি ভুলের জন্য অর্থ প্রদান করছেন। ৮০ এর দশকে, যখন সংকলকগুলি বিন্যাসের স্ট্রিংগুলি পরীক্ষা করতে যথেষ্ট ভাল না হয়, অপারেটর ওভারলোডিংকে আইওয়ের সময় কিছুটা সুরক্ষার সিম্বলেন্স প্রয়োগ করার একটি ভাল উপায় হিসাবে দেখা হত। তবে এর প্রতিটি ব্যানার বৈশিষ্ট্যই খারাপভাবে প্রয়োগ করা হয় বা ধারণা থেকেই দেউলিয়া শুরু থেকেই:

<Iomanip>

সি ++ স্ট্রিম আইও এপিআইয়ের সর্বাধিক বিতর্কিত অংশটি এই ফর্ম্যাট শিরোনাম লাইব্রেরির অস্তিত্ব। রাষ্ট্রীয় এবং কুরুচিপূর্ণ এবং ত্রুটি প্রবণ হওয়ার পাশাপাশি এটি দম্পতিরা ফর্ম্যাটে ফর্ম্যাট করে।

মনে করুন আপনি 8 টি শূন্য ভরা হেক্স সহ স্বাক্ষরবিহীন ইন্টের পরে একটি স্পেস এবং তারপরে 3 দশমিক স্থান সহ একটি ডাবল মুদ্রণ করতে চান। এর সাথে <cstdio>, আপনি একটি সংক্ষিপ্ত বিন্যাসের স্ট্রিং পড়তে পারেন। এর সাথে <ostream>, আপনাকে পুরানো অবস্থা সংরক্ষণ করতে হবে, ডানদিকে প্রান্তিককরণ সেট করতে হবে, পূরণের অক্ষর সেট করতে হবে, পূরণের প্রস্থকে সেট করতে হবে, হেক্সের ভিত্তিটি নির্ধারণ করবে, পূর্ণসংখ্যা আউটপুট হবে, সংরক্ষণিত অবস্থা পুনরুদ্ধার করতে হবে (অন্যথায় আপনার পূর্ণসংখ্যা বিন্যাসটি আপনার ভাসমান বিন্যাসকে দূষিত করবে), স্থান আউটপুট করুন , স্থির নোটেশন সেট, নির্ভুলতা সেট, ডাবল এবং নতুন লাইন আউটপুট, তারপরে পুরানো ফর্ম্যাটিং পুনরুদ্ধার।

// <cstdio>
std::printf( "%08x %.3lf\n", ival, fval );

// <ostream> & <iomanip>
std::ios old_fmt {nullptr};
old_fmt.copyfmt (std::cout);
std::cout << std::right << std::setfill('0') << std::setw(8) << std::hex << ival;
std::cout.copyfmt (old_fmt);
std::cout << " " << std::fixed << std::setprecision(3) << fval << "\n";
std::cout.copyfmt (old_fmt);

অপারেটর ওভারলোডিং

<iostream> অপারেটর ওভারলোডিং কীভাবে ব্যবহার করবেন না তার পোস্টার চাইল্ড:

std::cout << 2 << 3 && 0 << 5;

কর্মক্ষমতা

std::coutবেশ কয়েকবার ধীর printf()। বিস্তৃত বৈশিষ্ট্যযুক্ত বৈশিষ্ট্য এবং ভার্চুয়াল প্রেরণ এটির ক্ষতি করে।

থ্রেড সুরক্ষা

উভয় <cstdio>এবং <iostream>থ্রেড নিরাপদ যে প্রতিটি ফাংশন কল পারমাণবিক। কিন্তু, printf()কল প্রতি আরও অনেক কিছু সম্পন্ন হয়। আপনি যদি <cstdio>বিকল্পটি দিয়ে নিম্নলিখিত প্রোগ্রামটি চালান তবে আপনি কেবল একটি সারি দেখতে পাবেন f। আপনি যদি <iostream>কোনও মাল্টিকোর মেশিন ব্যবহার করেন তবে আপনি সম্ভবত অন্য কিছু দেখতে পাবেন।

// g++ -Wall -Wextra -Wpedantic -pthread -std=c++17 cout.test.cpp

#define USE_STREAM 1
#define REPS 50
#define THREADS 10

#include <thread>
#include <vector>

#if USE_STREAM
    #include <iostream>
#else
    #include <cstdio>
#endif

void task()
{
    for ( int i = 0; i < REPS; ++i )
#if USE_STREAM
        std::cout << std::hex << 15 << std::dec;
#else
        std::printf ( "%x", 15);
#endif

}

int main()
{
    auto threads = std::vector<std::thread> {};
    for ( int i = 0; i < THREADS; ++i )
        threads.emplace_back(task);

    for ( auto & t : threads )
        t.join();

#if USE_STREAM
        std::cout << "\n<iostream>\n";
#else
        std::printf ( "\n<cstdio>\n" );
#endif
}

এই উদাহরণটির প্রতিবেদনটি হ'ল বেশিরভাগ লোকেরা যে কোনও উপায়ে একাধিক থ্রেড থেকে কোনও একক ফাইল বর্ণনাকারীর কাছে কখনও না লেখার জন্য শৃঙ্খলা অনুশীলন করে। ভাল, যে ক্ষেত্রে, আপনি মান্য করতে যে আছে <iostream>সহায়কভাবে প্রত্যেক উপর একটি লক দখল করবে <<এবং প্রতি >>। যদিও <cstdio>, আপনি প্রায়শই লকিং করবেন না এবং আপনার কাছে লক না করার বিকল্পও রয়েছে।

<iostream> কম সামঞ্জস্যপূর্ণ ফলাফল অর্জন করতে আরও লক ব্যয় করে।


2
প্রিন্টফের বেশিরভাগ বাস্তবায়নের স্থানীয়করণের জন্য অত্যন্ত কার্যকর বৈশিষ্ট্য রয়েছে: সংখ্যাযুক্ত পরামিতি। আপনার যদি দুটি ভিন্ন ভাষায় (যেমন ইংরেজি এবং ফরাসী) কিছু শব্দ আউটপুট তৈরি করতে হয় এবং শব্দের ক্রম পৃথক হয় তবে আপনি একই প্রিন্টফকে ভিন্ন বিন্যাসের স্ট্রিং সহ ব্যবহার করতে পারেন এবং এটি বিভিন্ন ক্রমে প্যারামিটারগুলি মুদ্রণ করতে পারে।
gnasher729

2
স্ট্রিমের সেই রাষ্ট্রীয় বিন্যাসটি অবশ্যই আমি কী বলতে চাই তা জানি না এমন বাগগুলি খুঁজে পেতে অনেক বেশি কষ্ট দিয়েছিল। দুর্দান্ত উত্তর। যদি আমি পারতাম তবে একাধিকবার উত্সাহ দিতে হবে।
ম্যাথ্রেডলার

6
std::coutবেশ কয়েকবার ধীর printf()” - পুরো দাবীতে এই দাবিটি পুনরাবৃত্তি হয়েছে তবে এটি যুগে যুগে সত্য হয়নি। আধুনিক আইওস্ট্রিম প্রয়োগগুলি সমানভাবে সম্পাদন করে printf। পরবর্তীকৃত বাফার স্ট্রিম এবং স্থানীয়করণকৃত আইও (অপারেটিং সিস্টেম দ্বারা সম্পন্ন তবে তবুও সম্পন্ন হয়েছে) এর সাথে ডিল করার জন্য অভ্যন্তরীণভাবে ভার্চুয়াল প্রেরণ সম্পাদন করে।
কনরাড রুডলফ

3
@ কেভিনজেড এবং এটি দুর্দান্ত তবে এটি একটি একক, নির্দিষ্ট কলকে বেঞ্চমার্ক করছে, যা এফএমটি-র নির্দিষ্ট শক্তি (একক স্ট্রিংয়ে প্রচুর বিভিন্ন ফর্ম্যাট) প্রদর্শন করে। আরও সাধারণ ব্যবহারের মধ্যে printfএবং coutসংকোচনের পার্থক্য । ঘটনাচক্রে এই সাইটে প্রচুর পরিমাণে মানদণ্ড রয়েছে।
কনরাড রুডলফ

3
@ KonradRudolph- এ কথাটি সত্য নয়। মাইক্রোব্যাঙ্কমার্কগুলি প্রায়শই ফোটা এবং ইন্ডিরিয়েশনের ব্যয়কে অনুমান করে কারণ তারা নির্দিষ্ট সীমিত সংস্থানগুলি নিঃশেষ করে না (এটি নিবন্ধন, আইচাচি, স্মৃতিশক্তি, শাখার ভবিষ্যদ্বাণীকারী) যেখানে একটি আসল প্রোগ্রাম থাকবে। আপনি যখন "আরও সাধারণ ব্যবহার" দেখান, এটি মূলত বলে থাকে যে আপনার অন্য কোথাও যথেষ্ট ফোলাভাব রয়েছে, যা ভাল তবে বিষয় ছাড়াই। আমার মতে, আপনার যদি পারফরম্যান্সের প্রয়োজনীয়তা না থাকে, আপনার সি ++ তে প্রোগ্রাম করার দরকার নেই।
কেভিনজেড

18

কি সব অন্যান্য উত্তর বলেছি ছাড়াও,
এছাড়াও আছে সত্য যে std::endlহয় না হিসাবে একই '\n'

এটি দুর্ভাগ্যক্রমে সাধারণ ভুল ধারণা ception std::endl"নতুন লাইন" বলতে বোঝায় না, এর অর্থ "নতুন লাইন
প্রিন্ট করুন এবং তারপরে প্রবাহটি প্রবাহিত করুন "। ফ্লাশিং সস্তা নয়!

মধ্যে পার্থক্য সম্পূর্ণ উপেক্ষা printfstd::coutএক মুহুর্তের এবং আপনার সি উদাহরণটির সাথে কার্যকরীভাবে দক্ষ হতে, আপনার সি ++ উদাহরণটি দেখতে এইরকম হওয়া উচিত:

#include <iostream>

int main()
{
    std::cout << "Hello world\n";
    return 0;
}

এবং এখানে ফ্লাশিং অন্তর্ভুক্ত করা থাকলে আপনার উদাহরণগুলি কেমন হওয়া উচিত তার একটি উদাহরণ এখানে।

সি

#include <stdio.h>

int main()
{
    printf("Hello world\n");
    fflush(stdout);
    return 0;
}

সি ++

#include <iostream>

int main()
{
    std::cout << "Hello world\n";
    std::cout << std::flush;
    return 0;
}

কোডের তুলনা করার সময়, আপনাকে সর্বদা সতর্ক হওয়া উচিত যে আপনি পছন্দ মতো পছন্দ করছেন এবং আপনার কোডটি কী করছে তার প্রভাবগুলি বুঝতে understand কখনও কখনও এমনকি সহজ উদাহরণগুলি কিছু লোকেরা বুঝতে পারে তার চেয়ে বেশি জটিল complicated


আসলে, ব্যবহার করা std::endl হচ্ছে একটি লাইন-বাফার্ড স্টদিও স্ট্রিমে একটি নতুন লাইন লেখার সমতুল্য equivalent stdout, বিশেষত, ইন্টারেক্টিভ ডিভাইসের সাথে সংযুক্ত থাকাকালীন লাইন-বাফার বা আনফফার হওয়া প্রয়োজন। লিনাক্স, আমি বিশ্বাস করি, লাইন-বাফার্ড বিকল্পটিতে জোর দেয়।

বস্তুত, iostream গ্রন্থাগার নেই একটি লাইন-বাফার মোডে ... পথ লাইন বাফারিং প্রভাব অর্জন করা অবিকল ব্যবহার করা std::endlআউটপুট নতুন লাইন করতে।

@ হার্কাইল জিদ? তাহলে এর ব্যবহার কী setvbuf(3)? বা আপনি ডিফল্ট লাইন বাফার হয় মানে? এফওয়াইআই: সাধারণত সমস্ত ফাইল ব্লক বাফার হয়। যদি কোনও স্ট্রিম কোনও টার্মিনালকে বোঝায় (যেমন স্টডআউট সাধারণত করেন) তবে এটি লাইন বাফার হয়। স্ট্যান্ডার্ড ত্রুটি স্ট্রিমার সর্বদা ডিফল্টরূপে অশুভ থাকে।
প্রাইফটান

printfএকটি নতুন লাইনের চরিত্রের মুখোমুখি হওয়ার পরে কি স্বয়ংক্রিয়ভাবে ফ্লাশ হয় না ?
bool3max

1
@ bool3max যা আমার পরিবেশটি কী তা কেবল আমাকে জানায়, এটি অন্যান্য পরিবেশে ভিন্ন হতে পারে। এমনকি এটি সর্বাধিক জনপ্রিয় বাস্তবায়নের সমস্ত ক্ষেত্রে একই আচরণ করে, এর অর্থ এই নয় যে কোথাও কোনও প্রান্তের মামলা রয়েছে। এজন্য স্ট্যানার্ডটি এত গুরুত্বপূর্ণ - স্ট্যান্ডার্ড নির্দেশ দেয় যে সমস্ত বাস্তবায়নের জন্য কিছু একই হতে হবে বা বাস্তবায়নের মধ্যে এটির পরিবর্তিত হওয়ার অনুমতি রয়েছে কিনা।
ফারাপ

16

বিদ্যমান প্রযুক্তিগত উত্তরগুলি সঠিক হলেও, আমি মনে করি যে প্রশ্নটি শেষ পর্যন্ত এই ভুল ধারণা থেকে উদ্ভূত হয়েছে:

এটি বিখ্যাত যে সি ++ এ আপনি যা খান তার জন্য অর্থ প্রদান করেন।

এটি কেবল সি ++ সম্প্রদায় থেকে বিপণনের আলাপ। (সত্যি বলতে কী, প্রতিটি ভাষার সম্প্রদায়ের মধ্যে বিপণনের আলাপ রয়েছে)) এর অর্থ এমন কোনও কংক্রিট নয় যা আপনি গুরুত্ব সহকারে নির্ভর করতে পারেন।

"আপনি যা ব্যবহার করেন তার জন্য আপনি অর্থ প্রদান করেন" এর অর্থ হ'ল আপনি যদি সেই বৈশিষ্ট্যটি ব্যবহার করেন তবে একটি সি ++ বৈশিষ্ট্যটির ওভারহেড থাকে has তবে "একটি বৈশিষ্ট্য" এর সংজ্ঞা অসীম দানাদার নয়। প্রায়শই আপনি একাধিক দিক রয়েছে এমন বৈশিষ্ট্যগুলি সক্রিয় করে দেবেন এবং আপনার কেবল সেই দিকগুলির একটি উপসেট প্রয়োজন হলেও প্রায়শই ব্যবহারিক বা সম্ভাব্য নয় বৈশিষ্ট্যটি আংশিকভাবে আনা সম্ভব।

সাধারণভাবে, অনেকগুলি (যদিও তাত্ক্ষণিকভাবে সমস্ত নয়) ভাষা সাফল্যের বিভিন্ন ডিগ্রী সহ দক্ষ হওয়ার জন্য প্রচেষ্টা করে। সি ++ স্কেলটি কোথাও রয়েছে তবে এর নকশা সম্পর্কে বিশেষ বা যাদুকর কিছুই নেই যা এ লক্ষ্যে এটি পুরোপুরি সফল হতে দেয়।


1
আপনি যে জিনিসটি ব্যবহার করেন না তার জন্য আপনি কোথায় অর্থ প্রদান করেন সে সম্পর্কে আমি ভাবতে পারি মাত্র দুটি জিনিস: ব্যতিক্রম এবং আরটিটিআই। এবং আমি মনে করি না এটি বিপণনের আলোচনা; সি ++ মূলত আরও শক্তিশালী সি, এটি "আপনি যা ব্যবহার করেন তার জন্য অর্থ প্রদান করবেন না" এটিও।
Rakete1111

2
@ রেকেট 1111 এটি বহু আগে থেকেই প্রতিষ্ঠিত যে ব্যতিক্রমগুলি যদি না ফেলে তবে তাদের দাম পড়বে না। যদি আপনার প্রোগ্রামটি ধারাবাহিকভাবে ছোঁড়াচ্ছে তবে এটি নতুন করে ডিজাইন করা উচিত। যদি ব্যর্থতার শর্ত আপনার নিয়ন্ত্রণের বাইরে থাকে তবে শর্তটি মিথ্যা বলে নির্ভর করে এমন পদ্ধতিটি কল করার আগে আপনাকে বুল রিটার্নিং স্যানিটি চেক দিয়ে শর্তটি পরীক্ষা করা উচিত।
মাস্টার

1
@ স্কুলমাস্টার: সি ++ তে লিখিত কোডগুলিকে অন্য ভাষায় লিখিত কোডের সাথে ইন্টারঅ্যাক্ট করার প্রয়োজন হলে ব্যতিক্রমগুলি নকশার সীমাবদ্ধতা আরোপ করতে পারে, কারণ মডিউলগুলি একে অপরের সাথে কীভাবে সমন্বয় সাধন করতে পারে তা যদি নিয়ন্ত্রণের অ-স্থানীয় স্থানান্তর কেবল মডিউলগুলিতে সহজেই কাজ করতে পারে।
সুপারক্যাট

1
(যদিও যুক্তিযুক্তভাবে সমস্ত নয়) ভাষাগুলি দক্ষ হওয়ার জন্য প্রচেষ্টা করে । অবশ্যই সমস্ত নয়: এসোটেরিক প্রোগ্রামিং ভাষাগুলি উপন্যাস / আকর্ষণীয় হওয়ার জন্য প্রচেষ্টা করে, দক্ষ নয়। esolangs.org । তাদের মধ্যে কিছু, ব্রেইনফাক, বিখ্যাতভাবে অদক্ষ। বা উদাহরণস্বরূপ, শেকসপিয়র প্রোগ্রামিং ল্যাঙ্গুয়েজ, সমস্ত পূর্ণসংখ্যা মুদ্রণের জন্য 227 বাইট ন্যূনতম আকার (কোডগল্ফ) । উত্পাদন ব্যবহারের জন্য উদ্দিষ্ট ভাষাগুলির মধ্যে, বেশিরভাগ দক্ষতার জন্য লক্ষ্য রাখে, তবে কিছু (বাশের মতো) বেশিরভাগ সুবিধার জন্য লক্ষ্য করে এবং ধীর বলে পরিচিত।
পিটার কর্ডেস

2
ঠিক আছে, এটি বিপণন তবে এটি প্রায় সম্পূর্ণ সত্য। আপনি কীভাবে সংকলন করতে পারেন ঠিক তেমনই আপনি আটকে থাকতে পারেন <cstdio>এবং অন্তর্ভুক্ত <iostream>করতে পারবেন না -fno-exceptions -fno-rtti -fno-unwind-tables -fno-asynchronous-unwind-tables
কেভিনজেড

11

সি ++ এ ইনপুট / আউটপুট ফাংশনগুলি মার্জিতভাবে লিখিত হয় এবং ডিজাইন করা হয় যাতে এটি ব্যবহার করা সহজ। অনেক ক্ষেত্রে তারা সি ++ এ অবজেক্ট-ওরিয়েন্টেড বৈশিষ্ট্যগুলির জন্য একটি শোকেস।

তবে আপনি বিনিময়ে প্রকৃতপক্ষে কিছুটা পারফরম্যান্স ছেড়ে দেন, তবে এটি আপনার অপারেটিং সিস্টেমের দ্বারা নিম্ন স্তরে কাজগুলি পরিচালনার জন্য নেওয়া সময়ের তুলনায় নগন্য l

আপনি সি স্টাইলের ফাংশনগুলিতে সর্বদা ফিরে আসতে পারেন কারণ সেগুলি সি ++ স্ট্যান্ডার্ডের অংশ, বা সম্ভবত বহনযোগ্যতা ছেড়ে দেয় এবং আপনার অপারেটিং সিস্টেমে সরাসরি কল ব্যবহার করতে পারে।


23
"সি ++ এ ইনপুট / আউটপুট ফাংশনগুলি হ'ল ঘৃণ্য দৈত্যরা তাদের চথুলিয়ান প্রকৃতিটি উপযোগের পাতলা ব্যহ্যাবরণের আড়ালে লুকিয়ে রাখতে লড়াই করে many সম্ভবত আরও সঠিক হতে হবে।
ব্যবহারকারী 673679

3
@ ইউজার 673679: খুব সত্য Very সি ++ আই / ও স্ট্রিমগুলির দুর্দান্ত সমস্যাটি হ'ল নীচের বিষয়গুলি: সত্যিই এখানে অনেক জটিলতা চলছে, এবং যে কেউ তাদের সাথে যে কখনও আচরণ করেছেন (আমি std::basic_*streamনীচের দিকে রেফারিং করছি ) আগত কান্নাগুলি জানে। এগুলি ব্যাপকভাবে সাধারণ হিসাবে নকশাকৃত করা হয়েছিল এবং উত্তরাধিকারের মাধ্যমে প্রসারিত হয়েছিল; কিন্তু শেষ পর্যন্ত কেউ তা করেন নি, তাদের জটিলতার কারণে (আস্তে আস্তে আস্তে আস্তে আস্তে বই লেখা আছে) এতোটুকু নতুন লাইব্রেরি কেবল তার জন্যই জন্মগ্রহণ করেছিল (যেমন, বুস্ট, আইসিইউ ইত্যাদি)। আমি সন্দেহ করি আমরা কখনই এই ভুলটির জন্য অর্থ প্রদান বন্ধ করব।
এডিএমজেড

1

যেমন আপনি অন্যান্য উত্তরে দেখেছেন, আপনি যখন সাধারণ লাইব্রেরিতে লিঙ্ক করেন এবং জটিল নির্মাণকারীদের কল করেন তখন আপনি অর্থ প্রদান করেন। এখানে কোনও বিশেষ প্রশ্ন নেই, আরও গ্রিপ। আমি কিছু বাস্তব-বিশ্বের দিকগুলি উল্লেখ করব:

  1. বার্নের দক্ষতা ডিজিটাল নীতি ছিল যাতে দক্ষতা কখনও সি ++ এর চেয়ে সিতে থাকার কারণ হতে পারে না। এটি বলেছিল যে, এই দক্ষতাগুলি সম্পর্কে আমাদের সতর্ক হওয়া দরকার এবং মাঝে মধ্যে এমন দক্ষতা রয়েছে যা সবসময় কাজ করে তবে সি স্পেকের মধ্যে 'প্রযুক্তিগতভাবে' ছিল না। উদাহরণস্বরূপ, বিট ক্ষেত্রগুলির বিন্যাসটি প্রকৃতপক্ষে নির্দিষ্ট করা হয়নি।

  2. অস্ট্রিমে দেখার চেষ্টা করুন। হায় খোদা এটা ফুলে! আমি সেখানে একটি ফ্লাইট সিমুলেটর পেয়ে অবাক হব না। এমনকি stdlib এর প্রিন্টফ () সাধারণত প্রায় 50K চালায়। এগুলি অলস প্রোগ্রামার নয়: প্রিন্টফ আকারের অর্ধেকটি ছিল অপ্রত্যক্ষ নির্ভুলতা যুক্তি যা বেশিরভাগ মানুষ কখনও ব্যবহার করে না। প্রায় প্রতিটি সত্যই সীমাবদ্ধ প্রসেসরের লাইব্রেরি প্রিন্টফের পরিবর্তে নিজস্ব আউটপুট কোড তৈরি করে।

  3. আকারের বৃদ্ধিটি সাধারণত একটি আরও অন্তর্ভুক্ত এবং নমনীয় অভিজ্ঞতা সরবরাহ করে। সাদৃশ্য হিসাবে, একটি ভেন্ডিং মেশিন কয়েকটি কয়েনের জন্য এক কাপ কফি জাতীয় উপাদান বিক্রি করবে এবং পুরো লেনদেনটি এক মিনিটের মধ্যে সময় নেয়। একটি ভাল রেস্তোরাঁয় ফেলে দেওয়াতে একটি টেবিল সেটিং জড়িত থাকে, বসে থাকে, অর্ডার হয়, অপেক্ষা করা হয়, একটি ভাল কাপ পাওয়া যায়, বিল পাওয়া যায়, আপনার ফর্মগুলির পছন্দমতো অর্থ প্রদান করা, একটি টিপ যোগ করা এবং আপনার বেরোনোর ​​জন্য একটি ভাল দিন কামনা করা। যদি আপনি কোনও জটিল খাবারের জন্য বন্ধুদের সাথে ঘুরতে থাকেন তবে এটি একটি ভিন্ন অভিজ্ঞতা এবং আরও সুবিধাজনক।

  4. লোকেরা এখনও এএনএসআই সি লিখেন, যদিও খুব কমই কে ওআর সি হয় আমার অভিজ্ঞতাটি হ'ল আমরা যা কিছু টেনে আনে তা সীমাবদ্ধ করতে কয়েকটি কনফিগারেশন টুইট ব্যবহার করে একটি সি ++ সংকলক দিয়ে সর্বদা সংকলন করি other ; স্মার্ট ফিল্ড প্যাকিং এবং মেমরি লেআউটের জন্য কিছু ভাল যুক্তি রয়েছে। আইএমএইচএও আমি মনে করি যে কোনও ভাষার ডিজাইনের লক্ষ্যগুলির তালিকা দিয়ে শুরু করা উচিত, অনেকটা পাইথনের জেনের মতো ।

এটি একটি মজার আলোচনা হয়েছে। আপনি জিজ্ঞাসা করলেন কেন আপনার কাছে যাদুকরীভাবে ছোট, সরল, মার্জিত, সম্পূর্ণ এবং নমনীয় লাইব্রেরি থাকতে পারে না?

এর কোন উত্তর নেই. কোন উত্তর হবে না। এটাই উত্তর।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.