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

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

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
  • Проголосовать: не нравится

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +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://mirror.codeforces.com/blog/entry/87419?#comment-756655, https://mirror.codeforces.com/blog/entry/83672?#comment-709924

  • »
    »
    5 лет назад, скрыть # ^ |
    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.

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

    Thank you!

»
5 лет назад, скрыть # |
 
Проголосовать: нравится -86 Проголосовать: не нравится
Do you agree?
»
5 лет назад, скрыть # |
 
Проголосовать: нравится +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
»
5 лет назад, скрыть # |
 
Проголосовать: нравится +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.

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

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

»
5 лет назад, скрыть # |
 
Проголосовать: нравится -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;)

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +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)

»
2 года назад, скрыть # |
 
Проголосовать: нравится 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

»
20 месяцев назад, скрыть # |
 
Проголосовать: нравится +43 Проголосовать: не нравится

With Problem 2005-E2 - Subtangle Game (Hard Version), Codeforces is now openly telling people to use cout.tie(NULL);. I urge its authors, BiNARyBeastt and Tsovak, to read this blog and avoid spreading misinformation.

TLDR: Do not use cout.tie(0) since it does nothing.

  • »
    »
    20 месяцев назад, скрыть # ^ |
     
    Проголосовать: нравится +43 Проголосовать: не нравится

    Quoting purplesyringa:

    // If you use std::cout.tie(nullptr);, you are wrong.
    // This won't ever be supported.
    // You don't need this line. Remove it.
    // You have almost certainly added 12 useless bytes to every solution. They take space on disk.
    // Disks are produced by young children on factories. Do you want children to work more because
    // of you? Think of the children.
    // And about yourself too. One of the pictures on this page is loaded from my domain. I know your IP.
    
  • »
    »
    20 месяцев назад, скрыть # ^ |
     
    Проголосовать: нравится +17 Проголосовать: не нравится

    Thanks for the information. I've been using that in my template all the time lol. I'll change it on polygon soon.

  • »
    »
    16 месяцев назад, скрыть # ^ |
    Rev. 3  
    Проголосовать: нравится +42 Проголосовать: не нравится

    Recently there was another problem statement (2053G - Naive String Splits) by Cocoly1990 and Caylex telling people to use cout.tie(0).

    Cocoly1990 and Caylex, please do not tell people to use cout.tie(0) in C++ as it does absolutely nothing! cout.tie(0) is like the homeopathy of competitive programming.

    • »
      »
      »
      16 месяцев назад, скрыть # ^ |
       
      Проголосовать: нравится -57 Проголосовать: не нравится

      TL; DR I think it's only a matter of personal taste. I'm sorry for not knowing it before the contest, but after I learned about it, I still don't see any reason that I must delete it. Can you elaborate on how much negative effect it has given the codeforces community? I think that equals to zero.

      First of all, you've notified the wrong people. Cocoly is in Grade 12 and studying hard for the College Entrance Exam (known as Gaokao), and Caylex has never had access to the contest on Polygon.

      Secondly, this is not to "tell people to use xxx". I've never said this is the only way to fasten your input or output speed (and, even, some solutions without this buff can also pass comfortably).

      Thirdly, its doing absolutely nothing is not the reason that I should definitely delete it. If you really have such mysophobia, please ping the authors of Atcoder rounds not to display main correct solutions with tedious templates, as most do absolutely nothing if you are only learning the solution to a single problem.

      By the way, the coordinators of the two rounds are the same and it was Scrasse who sent me the message to add a notice similar to the 2005E2 problem. I assume that he has also seen the issue raised by you, but he didn't think it very important to remove cout.tie either.

      • »
        »
        »
        »
        16 месяцев назад, скрыть # ^ |
        Rev. 2  
        Проголосовать: нравится +43 Проголосовать: не нравится

        I don't think "what about AtCoder" argument stands... Similar situations would often turn out not so similar on a closer look, and in this particular case, templates are not part of the statement, don't explicitly encourage people to use specific template, and more importantly, they are useful in some scenarios, even if not in the specific problem.

        But actually I'd also support removing the templates when they're clearly not needed, but that's beyond the point. It's just that templates have less perceived negative impact and, more importantly, removing them might be a non-trivial task if the solution uses only small useful part of the template and you'd like to get rid of useless parts. So, keeping them has at least some reasonable arguments, unlike keeping cout.tie(0).

        I think the main reason not to use cout.tie(0) is that using it promotes a cargo cult-like approach to coding, where you just treat some commands as magic without putting much consideration into what they actually do. Not like removing it immediately promotes better practices, but at least it doesn't promote the bad ones that openly.

        In any case, please treat it as a request to follow certain best practices, and not as a personal attack. Putting it there is not a stylistic preference like using tabs vs spaces or 0 vs NULL vs nullptr. I really see no viable argument to keep using cout.tie, other than the fact that pointing it out is a criticism and it in itself might trigger a defensive response.

      • »
        »
        »
        »
        16 месяцев назад, скрыть # ^ |
        Rev. 2  
        Проголосовать: нравится +27 Проголосовать: не нравится

        It seems that many people actually care, so I've just updated the statement of 2005E2 - Subtangle Game (Hard Version). For some reason, I see the new statement on Polygon but I still see the old statement on Codeforces.

        I cannot update the statement of 2053G - Naive String Splits because the problem is too "heavy" at the moment (high time limit, many solutions and tests) and Polygon does not allow me to create a package without exceeding my quota :D