কিভাবে স্ট্যান্ড :: ফ্লাশ কাজ করে?


85

কেউ দয়া করে ব্যাখ্যা করতে পারেন (পছন্দমত প্লেইন ইংলিশ ব্যবহার করে) কীভাবে std::flushকাজ করে?

  • এটা কি?
  • আপনি কখন কোন প্রবাহ প্রবাহিত করবেন?
  • এটা কেন গুরুত্বপূর্ণ?

ধন্যবাদ.

উত্তর:


140

যেহেতু কী std::flush হবে তা উত্তর দেওয়া হয়নি , সুতরাং এটি আসলে কী তা সম্পর্কে এখানে কিছু বিশদ। std::flushএকটি ম্যানিপুলেটর , অর্থাত্ একটি নির্দিষ্ট স্বাক্ষরযুক্ত একটি ফাংশন। সহজ শুরু করতে, আপনি std::flushস্বাক্ষর থাকার কথা ভাবতে পারেন

std::ostream& std::flush(std::ostream&);

বাস্তবতা কিছুটা জটিল, যদিও (আপনি যদি আগ্রহী হন তবে এটি নীচেও ব্যাখ্যা করা হয়েছে)।

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

std::ostream& std::ostream::operator<< (std::ostream& (*manip)(std::ostream&)) {
    (*manip)(*this);
    return *this;
}

এটি হ'ল, যখন আপনি std::flushএকটি এর সাথে "আউটপুট" করেন std::ostream, এটি কেবলমাত্র সংশ্লিষ্ট ফাংশনটিকে কল করে, যেমন, নিম্নলিখিত দুটি বিবৃতি সমান:

std::cout << std::flush;
std::flush(std::cout);

এখন, std::flush()নিজেই মোটামুটি সহজ: এটি করার জন্য সমস্ত কল করা হয় std::ostream::flush(), অর্থাত্, আপনি এর বাস্তব রূপটি এরকম কিছু দেখার জন্য কল্পনা করতে পারেন:

std::ostream& std::flush(std::ostream& out) {
    out.flush();
    return out;
}

std::ostream::flush()ফাংশন টেকনিক্যালি আহ্বান std::streambuf::pubsync()প্রবাহ বাফার বহিরাগত গন্তব্যে অক্ষর বাফার উপলব্ধ এবং পাঠানোর অক্ষর যখন ব্যবহৃত বাফার ওভারফ্লো হবে অথবা যখন অভ্যন্তরীণ উপস্থাপনা সাথে সিঙ্ক করা উচিত জন্য দায়ী: প্রবাহ বাফার (যদি থাকে) যা প্রবাহ সঙ্গে যুক্ত করা হয় উপর বাহ্যিক গন্তব্য, অর্থাত্‍ যখন ডেটা ফ্লাশ করা হয়। বাহ্যিক গন্তব্যের সাথে সিঙ্কক্রিয়ার ক্রমিক স্ট্রিমের অর্থ হ'ল যে কোনও বাফার অক্ষর তাত্ক্ষণিকভাবে প্রেরণ করা হয়েছে। এটি হ'ল std::flushস্ট্রিম বাফারকে তার আউটপুট বাফারটি ফ্লাশ করে। উদাহরণস্বরূপ, যখন কনসোলে ফ্লাশিং ডেটা লেখা হয় তখন কনসোলটিতে অক্ষরগুলি এই মুহুর্তে উপস্থিত হয়।

এটি প্রশ্ন উত্থাপন করতে পারে: অবিলম্বে চরিত্রগুলি কেন লেখা হয় না? সহজ উত্তরটি হ'ল অক্ষরগুলি লেখার জন্য সাধারণত মোটামুটি ধীর। যাইহোক, যুক্তিসঙ্গত পরিমাণে অক্ষর লিখতে যে পরিমাণ সময় লাগে এটি কেবল যেখানে লেখার জন্য একই রকম। অক্ষরের পরিমাণ অপারেটিং সিস্টেমের অনেকগুলি বৈশিষ্ট্য, ফাইল সিস্টেম ইত্যাদির উপর নির্ভর করে তবে প্রায়শই 4 ক অক্ষরের মতো প্রায় একই সময়ে প্রায় এক অক্ষর হিসাবে রচিত হয়। সুতরাং, বাহ্যিক গন্তব্যের বিবরণগুলির উপর নির্ভর করে বাফার ব্যবহার করে অক্ষরগুলি প্রেরণের আগে তাদের বাফারিং করা একটি বিশাল কর্মক্ষমতা উন্নতি হতে পারে।

উপরেরটি আপনার তিনটি প্রশ্নের দুটি উত্তর দিতে হবে। বাকী প্রশ্নটি: আপনি কখন কোন স্রোত বর্ষণ করবেন? উত্তরটি হল: অক্ষরগুলি কখন বাহ্যিক গন্তব্যে লেখা উচিত! এই ফাইল লেখার শেষে হতে পারে ব্যবহারকারীর ইনপুট (নোট যে জন্য জিজ্ঞাসা করার আগে (পরোক্ষভাবে একটি ফাইল বন্ধ করে বাফার flushes যদিও) অথবা অবিলম্বে std::coutস্বয়ংক্রিয়ভাবে থেকে পড়া রাঙা হয় std::cinযেমন std::coutহয় std::istream::tie()'ঘ std::cin)। যদিও এমন কয়েকটি অনুষ্ঠান হতে পারে যেখানে আপনি স্পষ্টভাবে একটি স্ট্রিম ফ্লাশ করতে চান তবে আমি সেগুলি মোটামুটি বিরল বলে মনে করি।

পরিশেষে, আমি প্রতিশ্রুতি দিয়েছি std::flushআসলে কী তার একটি সম্পূর্ণ চিত্র দেওয়ার জন্য: স্ট্রিমগুলি শ্রেণীর টেম্পলেটগুলি বিভিন্ন চরিত্রের ধরণের সাথে व्यवहार করতে সক্ষম হয় (বাস্তবে তারা কাজ করে charএবং wchar_tঅন্য চরিত্রের সাথে তাদের কাজ করা বেশ জড়িত যদিও আপনি সত্যই দৃ determined়প্রতিজ্ঞ হলে )। std::flushসমস্ত স্ট্রিমের তাত্পর্য সহ ব্যবহার করতে সক্ষম হতে , এটি এর মতো স্বাক্ষরের সাথে একটি ফাংশন টেম্পলেট হতে পারে:

template <typename cT, typename Traits>
std::basic_ostream<cT, Traits>& std::flush(std::basic_ostream<cT, Traits>&);

এটি std::flushতাত্ক্ষণিকভাবে তাত্ক্ষণিকভাবে ব্যবহার করার সময় std::basic_ostreamএটি কোনও বিষয় নয়: সংকলক স্বয়ংক্রিয়ভাবে টেমপ্লেট আর্গুমেন্টগুলি কেটে দেয়। তবে, এই ফাংশনটিতে টেমপ্লেট আর্গুমেন্ট ছাড়ের সুবিধার্থে কোনও কিছুর সাথে একত্রে উল্লেখ করা হয়নি, সংকলক টেমপ্লেট আর্গুমেন্টগুলি ব্যয় করতে ব্যর্থ হবে।


4
চমত্কার উত্তর। অন্য কোথাও ফ্লাশ কীভাবে কাজ করেছে সে সম্পর্কে মানের তথ্য খুঁজে পাওয়া যায়নি।
মাইকেল

32

ডিফল্টরূপে, std::coutবাফার করা হয় এবং বাফারটি পূর্ণ হয়ে গেলে বা অন্য কোনও ফ্লাশিং পরিস্থিতি দেখা দেয় তবে প্রকৃত আউটপুট কেবল মুদ্রিত হয় (উদাহরণস্বরূপ স্ট্রিমে একটি নতুন লাইন)। কখনও কখনও আপনি নিশ্চিত করতে চান যে মুদ্রণটি তত্ক্ষণাত ঘটেছিল এবং আপনাকে ম্যানুয়ালি ফ্লাশ করতে হবে।

উদাহরণস্বরূপ, ধরুন আপনি একটি ডট মুদ্রণ করে একটি অগ্রগতি প্রতিবেদন করতে চান:

for (;;)
{
    perform_expensive_operation();
    std::cout << '.';
    std::flush(std::cout);
}

ফ্লাশিং ছাড়া আপনি খুব দীর্ঘ সময়ের জন্য আউটপুটটি দেখতে পাবেন না।

নোট করুন যে std::endlএকটি স্ট্রিমে একটি নতুনলাইন সন্নিবেশ করানোর পাশাপাশি এটি প্রবাহিত করতে পারে। যেহেতু ফ্লাশিং হালকা ব্যয়বহুল, std::endlতাই ফ্লাশিং স্পষ্টভাবে পছন্দসই না হলে অতিরিক্ত ব্যবহার করা উচিত নয়।


7
পাঠকদের জন্য কেবল একটি অতিরিক্ত নোট: coutসি ++ এ কেবল একমাত্র জিনিস নয়। ostreamসাধারণভাবে সাধারণত ডিফল্ট হিসাবে বাফার হয়, যার মধ্যে fstreamএস এবং এর মতো কিছু রয়েছে ।
কর্নস্টালক

এছাড়াও cinআউটপুটটি ফ্লাশ হওয়ার আগেই ব্যবহার করে, না?
জায়েদ খান

21

এখানে একটি ছোট প্রোগ্রাম যা আপনি ফ্লাশ কি করছে তা পর্যবেক্ষণ করতে লিখতে পারেন

#include <iostream>
#include <unistd.h>

using namespace std;

int main() {

    cout << "Line 1..." << flush;

    usleep(500000);

    cout << "\nLine 2" << endl;

    cout << "Line 3" << endl ;

    return 0;
}

এই প্রোগ্রামটি চালান: আপনি লক্ষ্য করবেন যে এটি লাইন 1 টি, বিরাম দেয়, তারপরে লাইন 2 এবং 3 প্রিন্ট করে Now একই সময়. প্রোগ্রামটি বিরতি দেওয়ার আগে প্রথম লাইনটি বাফার করা হয়, তবে বাফারটি কখনই ফ্লাশ হয় না, লাইন 1 লাইন 2 থেকে আন্ডার কল না হওয়া পর্যন্ত আউটপুট করা হয় না।


এটি চিত্রিত করার আরেকটি উপায় হ'ল cout << "foo" << flush; std::abort();। আপনি যদি মন্তব্য / অপসারণ করেন << flush, তবে আউটপুট নেই! পিএস: স্ট্যান্ডার্ড-আউট-ডিবাগিং ডিএলএলগুলি যে কলটি abortদুঃস্বপ্ন। ডিএলএলদের কখনও কল করা উচিত নয় abort
মার্ক স্টোর

5

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

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

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

সুতরাং একটি ফ্লাশ একটি ধরণের চেকপয়েন্ট।

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

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