Блог пользователя peltorator

Автор peltorator, 3 года назад, По-английски

When you use C++ and the input is really big you can't just use cin and cout. You need to speed up it with

ios::sync_with_stdio(0);
cin.tie(0);

Someone argues that the second line is unnecessary but it's not true. if the input and output alternate then adding the second line makes I/O more than twice faster. But then... Someone argues that we also need to use cout.tie(0).

I personally never use this and I don't know any case where it can help. So my question for today is the following: "Is there any case where we actually need cout.tie? Or is it completely useless?"

  • Проголосовать: нравится
  • +276
  • Проголосовать: не нравится

»
3 года назад, # |
  Проголосовать: нравится +90 Проголосовать: не нравится

I have read several comments related to it by a user -is-this-fft- and I quote "cout.tie(NULL) does literally nothing because cout is already tied to NULL", "It sounds very strange when you consider what tie does. Every input or output stream in C++ is tied to an ostream or to null. Tyig cin to null means it's not tied to cout anymore which can speed things up. But cout is generally already tied to null."

Link to the comments — https://codeforces.com/blog/entry/87419?#comment-756655, https://codeforces.com/blog/entry/83672?#comment-709924

  • »
    »
    3 года назад, # ^ |
    Rev. 2   Проголосовать: нравится +479 Проголосовать: не нравится

    Yes, you are correct.

    I think it would be good to reiterate what tie does because I see a lot of people copying these lines with only a vague understanding of what they do.

    Every stream in C++ is tied to an output stream, which can be null.

    What does this mean? First of all, it's important to understand that when you write std::cout << "asdf", it is not necessarily immediately printed on the screen. It turns out that it is much better (in terms of performance) to collect it into a buffer and then, at some point, flush the buffer — i.e. empty its contents to the screen (or file, or any other "device"), all at once.

    But now, consider the following. You are developing a console application and write something like:

    1 std::cout << "Please enter your age: ";
    2 int age;
    3 std::cin >> age;
    

    What would happen if std::cout didn't get flushed before line 3? The program would expect a reply from the user, but the user hasn't even had a chance to read the question. In an application like this, it would be a good idea if std::cout was somehow automatically flushed when we try to read from std::cin.

    And this is exactly the problem tie solves. If you have two streams fin and fout, and fin is tied to fout, then fout is automatically flushed when you try to read from fin. So what are the defaults? What is tied to what? Quoting the C++ reference:

    By default, the standard narrow streams cin and cerr are tied to cout, and their wide character counterparts (wcin and wcerr) to wcout. Library implementations may also tie clog and wclog.

    Now it becomes clear why people recommend using cin.tie(0) in competitive programming. Suppose you are solving a query problem like this.

    1 MyAwesomeDataStructure ds;
    2 for (int i = 0; i < queryc; i++) {
    3   Query q;
    4   cin >> q;
    5   cout << ds.solve(q) << '\n';
    6 }
    

    If you didn't use cin.tie(0), we would flush cout every time we hit line 4; this is essentially as bad as writing endl on line 5. Concerns about the user not seeing the question are also irrelevant now because we are given the entire input at once.

    The reference doesn't explicitly say that cout isn't tied to anything, but on every C++ compiler I tried, cout << cout.tie() << endl; outputs 0. Also, even if you are using some strange compiler that ties cout to some other stream sout, you would only notice the performance hit if you wrote a lot to sout which doesn't really happen in competitive programming.

    So yes, cout.tie(0) doesn't do anything and in some sense it's a sign that the user doesn't understand cin.tie(0) very well either.

    • »
      »
      »
      3 года назад, # ^ |
        Проголосовать: нравится -140 Проголосовать: не нравится

      While you are probably right in the sense that what you are saying is correct, I think it is a wrong way to understand cin.tie(0) in competitive programming. And the last line from your comment for me proves that you are wrong. The last line reads like the fact that "the user doesn't understand it" is bad somehow. I don't agree.

      cin.tie(0) is just a bullshit line to make cin faster. I don't give a fuck what it does inside or how it works or why it even exists. The same with using namespace std — it's just something that stupid computer needs to understand you, that's it.

      • »
        »
        »
        »
        3 года назад, # ^ |
          Проголосовать: нравится +296 Проголосовать: не нравится

        Well, I don't think it is very bad to not know what tie does. Still, I prefer to know these things to prevent any unpleasant surprises.

        • »
          »
          »
          »
          »
          3 года назад, # ^ |
            Проголосовать: нравится +446 Проголосовать: не нравится

          Sorry, you answered a question that Um_nik wasn't interested in knowing the answer to. Please apologize for wasting his time.

        • »
          »
          »
          »
          »
          3 года назад, # ^ |
          Rev. 2   Проголосовать: нравится +18 Проголосовать: не нравится

          Thanks. Now I completely understand why using tie would recieve Idleness Limit Exceeded for those interactive problems. :D

      • »
        »
        »
        »
        3 года назад, # ^ |
          Проголосовать: нравится +21 Проголосовать: не нравится

        Um_nik, a guy with zero haters

    • »
      »
      »
      3 года назад, # ^ |
        Проголосовать: нравится +66 Проголосовать: не нравится

      Why do we still need to flush the buffer for interactive problems if one has not added cin.tie(0)?

      • »
        »
        »
        »
        3 года назад, # ^ |
          Проголосовать: нравится +44 Проголосовать: не нравится

        You know, I'm starting to think that you don't. I just went and resubmitted some solved interactive problems, removing any endl (those flush the output) and making sure there is no cin.tie(0). All of them got Accepted. Then I added cin.tie(0) and got (I think for the first time ever) the Idleness Limit Exceeded verdict.

    • »
      »
      »
      3 года назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Your answer is very good but I mistakenly voted against, I'm sorry...

  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится +26 Проголосовать: не нравится

    Thank you!

»
3 года назад, # |
  Проголосовать: нравится -86 Проголосовать: не нравится
Do you agree?
  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится +1 Проголосовать: не нравится

    I've seen your comments a lot lately on a lot of blogs. Now I think you're the one seeking +ve contribution.

»
3 года назад, # |
  Проголосовать: нравится +33 Проголосовать: не нравится

cout.tie(0) is not necessary, because by default cin ties with cout, but cout ties with nullptr so it's basically does nothing.

You can check it by code:

Spoiler
»
3 года назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

If you do not properly understand, what cin.tie(smth) and cout.tie(smth) do, you might want to write them all together. It doesn't slow your code down (does it?) and it decreases the chance you mix them up and write only cout.tie(nullptr) instead of cin.tie(nullptr).

I have somehow memorized that cout.tie(nullptr) is useless and excluded it from my pre-written pattern. I also do not write it in competitions that doesn't allow participants to use pre-written code. I don't know a simple way to remember, which string is useless (is cin kind of tied to cout, or is it the opposite?). So, I have just realised, it is better to write both of them.

  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится +18 Проголосовать: не нравится

    You're absolutely right. This question isn't about practice usage. I'm just interested in this.

»
3 года назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится

Should we use cin.tie(0); in Interactive Problems where next input depends on what we print using cout?

  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится +5 Проголосовать: не нравится

    I think there isn't actually any need for fast IO in interactive problems most of the time because we use flush and it's really slow. But at the same time, there is no reason not to use fast IO always.

»
3 года назад, # |
  Проголосовать: нравится -49 Проголосовать: не нравится

"Once and forever".... What a joke)
There still exists people that don't know that comparator must return true if and only if lhs is strictly less than rhs.

cout.tie in competitive programming is useless AFAIK. But it is usefull when you need to guarantee that you write in tied output strictly before cout. But I don't know when there is need for it;)

»
3 года назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится

Well, I also had a question related to this, that Is their any difference btw ios_base::sync_with_stdio(false); cin.tie(NULL); and cin.tie(0)->sync_with_stdio(0);(i saw this in Benq's template)

  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Both do same
    But I'd say first is preferable since second way is confusing. sync_with_stdio is static method and it supposed to be called as static not as member of cout.

»
4 месяца назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

I am not sure of the logic behind it, but on a dp question on cses, my code gave runtime error without cout.tie(NULL) and got accepted when i added that line. https://cses.fi/paste/2f6f0fdf60a71e537a397d/ try submitting this same code without the cout.tie(NULL) line. it should give you a good idea