how does cout << actually work?

后端 未结 1 1717
天涯浪人
天涯浪人 2020-12-08 01:49

I was wondering how std::cout is able to use << as it does.

My main puzzlement is with whether std::cout as an instance

相关标签:
1条回答
  • 2020-12-08 02:41

    std::cout is an instance of std::ostream. std::cout << "something" calls one of the operator<< overloads as would be done for any instance of std::ostream.

    It's "special" in that it references the console, but otherwise it behaves exactly as an ofstream or an ostringstream would.

    EDIT: Chaining works just like it works for any other operators. Consider:

    class MyType
    {
        friend std::ostream& operator<<(std::ostream& target, const MyType& source);
        int val;
    public:
        MyType()
            : val(0)
        { }
        MyType& Add(int toAdd)
        {
            val += toAdd;
            return *this;
        }
    };
    
    MyType& operator+(MyType& target, int toAdd)
    {
        return target.Add(toAdd);
    }
    
    std::ostream& operator<<(std::ostream& target, const MyType& source)
    {
        target << source.val;
        return target; //Make chaining work
    }
    
    int main()
    {
        MyType value1;
        value1 + 2 + 3 + 4;
        std::cout << value1 << " and done!" << std::endl;
    }
    

    In this case, the chaining for +s on MyType work for the same reason the <<s work on top of std::ostream. Both + and << are left-associative, which means they're evaluated from left to right. In the case of overloaded operators, the operator is replaced with the equivalent function call.

    EDIT2: In a bit more detail:

    Let's say you're the compiler and you're parsing

    std::cout << value1 << " and done!" << std::endl;
    

    First, << is left associative, so you start on the left. You evaluate the first << and turn it into the function call:

    operator<<(std::cout, value1) << " and done!" << std::endl;
    

    You then see that you once again have a std::ostream (the result of the call to operator<<), and a char *, which you once again turn into the function call:

    operator<<(operator<<(std::cout, value1)," and done!") << std::endl;
    

    and so on until you've processed the entire statement.

    0 讨论(0)
提交回复
热议问题