سؤال

تحتوي العديد من كتب C++ على رمز مثال مثل هذا...

std::cout << "Test line" << std::endl;

...لذا كنت أفعل ذلك دائمًا أيضًا.لكنني رأيت الكثير من التعليمات البرمجية من المطورين العاملين مثل هذا بدلاً من ذلك:

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

هل هناك سبب تقني لتفضيل أحدهما على الآخر، أم أن الأمر مجرد مسألة أسلوب ترميز؟

هل كانت مفيدة؟

المحلول

والشخصيات تنتهي خط متفاوتة لا يهم، على افتراض أن ملف مفتوح في وضع النص، وهو ما تحصل عليه إلا إذا كنت تسأل عن ثنائي. والبرنامج المترجمة الكتابة خارج الشيء الصحيح لنظام تجميع ل.

والفرق الوحيد هو أن std::endl الإحمرار المخزن المؤقت للإخراج، و '\n' لا. إذا كنت لا تريد المخزن المؤقت مسح كثير من الأحيان، استخدام '\n'. إذا قمت بذلك (على سبيل المثال، إذا كنت ترغب في الحصول على كل الإخراج، وبرنامج غير مستقرة)، استخدم std::endl.

نصائح أخرى

ويمكن توضيح الفرق من خلال ما يلي:

std::cout << std::endl;

يعادل

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

لذا،

  • يستخدم std::endl إذا كنت تريد فرض تدفق فوري للإخراج.
  • يستخدم \n إذا كنت قلقًا بشأن الأداء (وهذا على الأرجح ليس هو الحال إذا كنت تستخدم << المشغل أو العامل).

أنا أستعمل \n على معظم الخطوط.
ثم استخدام std::endl في نهاية الفقرة (لكن هذه مجرد عادة وليست ضرورية في العادة).

وخلافا للادعاءات الأخرى، فإن \n يتم تعيين الحرف إلى نهاية تسلسل السطر للنظام الأساسي الصحيح فقط إذا كان الدفق ينتقل إلى ملف (std::cin و std::cout كونها خاصة ولكنها لا تزال ملفات (أو تشبه الملف)).

وربما تكون هناك مشكلات في الأداء، std::endl يفرض تدفق للتيار الناتج.

تذكرت أنني قرأت عن هذا في المعيار، فإليك ما يلي:

راجع معيار C11 الذي يحدد كيفية تصرف التدفقات القياسية، حيث أن برامج C++ هي واجهة CRT، يجب أن يحكم معيار C11 سياسة التنظيف هنا.

ISO/IEC 9899:201x

7.21.3 §7

في بدء التشغيل ، يتم تعريف ثلاثة تدفقات نصية مسبقًا ولا يلزم فتحها بشكل صريح - المدخلات القياسية (لقراءة المدخلات التقليدية) ، والإخراج القياسي (لكتابة الإخراج التقليدي) ، والخطأ القياسي (لكتابة الإخراج التشخيصي).كما تم فتحه في البداية ، لا يتم تخزين دفق الخطأ القياسي بالكامل ؛يتم تخزين تدفقات الإدخال القياسية ودفقات الإخراج القياسية تمامًا إذا كان يمكن تحديد الدفق حتى لا يشير إلى جهاز تفاعلي.

7.21.3 §3

عندما يكون الدفق غير معتمد ، يهدف الشخصيات إلى الظهور من المصدر أو في الوجهة في أقرب وقت ممكن.خلاف ذلك قد يتم تجميع الشخصيات ونقلها من أو إلى البيئة المضيفة ككتلة.عندما يتم تخزين الدفق بالكامل ، يهدف الشخصيات إلى نقلها إلى أو من بيئة المضيف ككتلة عند ملء المخزن المؤقت.عندما يتم تخزين الدفق للخطوط ، يهدف الشخصيات إلى نقلها إلى أو من بيئة المضيف ككتلة عند مواجهة حرف جديد.علاوة على ذلك ، يهدف الشخصيات إلى نقل الأحرف ككتلة إلى بيئة المضيف عند ملء المخزن المؤقت ، أو عند طلب الإدخال في دفق غير محصور ، أو عند طلب الإدخال على دفق مخزن مؤقت يتطلب نقل الأحرف من بيئة المضيف .دعم هذه الخصائص محددة للتنفيذ ، وقد يتأثر من خلال وظائف setbuf و setvbuf.

هذا يعني ذاك std::cout و std::cin مخزنة بالكامل إذا وفقط إذا إنهم يشيرون إلى جهاز غير تفاعلي.بمعنى آخر، إذا تم إرفاق stdout بالمحطة، فلن يكون هناك اختلاف في السلوك.

ومع ذلك، إذا std::cout.sync_with_stdio(false) يسمى إذن '\n' لن يسبب تدفقًا حتى للأجهزة التفاعلية.خلاف ذلك '\n' يعادل std::endl ما لم يتم نقل الأنابيب إلى الملفات: مرجع c++ على std::endl.

وهناك استدعاء دالة أخرى تنطوي عليها هناك إذا كنت تنوي استخدام std::endl

a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;

وأ) يدعو مشغل << مرة واحدة.
ب) يدعو مشغل << مرتين.

وانهم على حد سواء كتابة الأحرف المناسبة في نهاية الخط (ق). وبالإضافة إلى ذلك ENDL سوف يسبب المخزن المؤقت إلى أن يلتزم. وعادة ما كنت لا تريد استخدام ENDL عند القيام ملف I / O لأن يرتكب لا لزوم لها يمكن أن تؤثر على الأداء.

ليست مشكلة كبيرة، ولكن لن يعمل endl في دفعة::لامدا.

(cout<<_1<<endl)(3); //error

(cout<<_1<<"\n")(3); //OK , prints 3

إذا كنت تستخدم كيو تي وENDL، هل يمكن عن طريق الخطأ استخدام endl خطأ، حدث لي اليوم وكنت مثل ..WTF ؟؟

#include <iostream>
#include <QtCore/QtCore> 
#include <QtGui/QtGui>
//notice that i dont have a "using namespace std;"
int main(int argc, char** argv)
{
    QApplication qapp(argc,argv);
    QMainWindow mw;
    mw.show();
    std::cout << "Finished Execution !" << endl << "...";
    // Line above printed: "Finished Execution !67006AB4..."
    return qapp.exec();
}

وبالطبع كان ذلك خطأي، وبما أنني يجب أن كتبوا std::endl، <الصورة> لكن إذا كنت تستخدم endl، كيو تي وusing namespace std; ذلك يعتمد على ترتيب ملفات التضمين إذا كان سيتم استخدام endl صحيح. *

وبطبيعة الحال يمكن إعادة ترجمة كيو تي لاستخدام مساحة الاسم، حتى تحصل على خطأ تجميع للمثال أعلاه.

وتحرير: نسيت أن أذكر، وأعلن endl كيو تي في "qtextstream.h" الذي هو جزء من QtCore

و* EDIT2: سوف C ++ يختارون endl صحيح إذا كان لديك using لstd::cout أو std مساحة الاسم، منذ std::endl في نفس مساحة الاسم كما std::cout، سوف C ++ الصورة آلية ADL اختيار std::endl

ولقد كان دائما عادة فقط باستخدام الأمراض المنقولة جنسيا :: ENDL لأنه من السهل بالنسبة لي أن أرى.

مع مرجع هذا معالج الإدخال/الإخراج فقط.

std::endl يقوم بإدراج حرف السطر الجديد في نظام التشغيل تسلسل الإخراج ويمسحه كما لو كان عن طريق الاتصال os.put(os.widen('\n')) تليها os.flush().

متى يجب استخدام:

يمكن استخدام هذا المناور لإنتاج خط من الإخراج على الفور,

على سبيل المثال

عند عرض مخرجات عملية طويلة الأمد، أو تسجيل نشاط سلاسل رسائل متعددة، أو تسجيل نشاط برنامج قد يتعطل بشكل غير متوقع.

أيضًا

يعد التدفق الصريح لـ std::cout ضروريًا أيضًا قبل استدعاء std::system، إذا كانت العملية الناتجة تنفذ أي إدخال/إخراج للشاشة.في معظم سيناريوهات الإدخال/الإخراج التفاعلية المعتادة الأخرى، يكون std::endl زائدًا عن الحاجة عند استخدامه مع std::cout لأن أي إدخال من std::cin، أو الإخراج إلى std::cerr، أو إنهاء البرنامج يفرض استدعاء std::cout .تدفق ().قد يؤدي استخدام std::endl بدلاً من ' '، والذي تشجعه بعض المصادر، إلى انخفاض أداء الإخراج بشكل كبير.

إذا كنت تنوي تشغيل البرنامج على أي شيء آخر من الكمبيوتر المحمول الخاص بك، لا تستخدم أي وقت مضى البيان endl. خاصة إذا كنت تكتب الكثير من خطوط قصيرة أو كما قلت غالبا ما ينظر أحرف واحدة إلى ملف. استخدام endl ويعرف لقتل أنظمة الملفات المتصلة بالشبكة مثل NFS.

وومناور endl ما يعادل '\'. لكن endl دائما الإحمرار الدفق.

std::cout << "Test line" << std::endl; // with flush
std::cout << "Test line\n"; // no flush

إذا لم يلاحظوا، endl مثل الضغط على مفتاح Enter في حين "\n" مثل الضغط على مفتاح Enter + SPACE BAR.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top