cout order of call to functions it prints?
There's no sequence point with the <<
operator so the compiler is free to evaluate either dequeue
function first. What is guaranteed is that the result of the second dequeue
call (in the order in which it appears in the expression and not necessarily the order in which it is evaluated) is <<
'ed to the result of <<
'ing the first (if you get what I'm saying).
So the compiler is free to translate your code into some thing like any of these (pseudo intermediate c++). This isn't intended to be an exhaustive list.
auto tmp2 = myQueue.dequeue();
auto tmp1 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
tmp3 << tmp2;
or
auto tmp1 = myQueue.dequeue();
auto tmp2 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
tmp3 << tmp2;
or
auto tmp1 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
auto tmp2 = myQueue.dequeue();
tmp3 << tmp2;
Here's what the temporaries correspond to in the original expression.
cout << myQueue.dequeue() << myQueue.dequeue();
| | | | |
| |____ tmp1 _____| |_____ tmp2 ____|
| |
|________ tmp3 _________|
order of function call inside cout
As stated here: https://en.cppreference.com/w/cpp/language/eval_order
Order of evaluation of any part of any expression, including order of
evaluation of function arguments is unspecified (with some exceptions
listed below). The compiler can evaluate operands and other
subexpressions in any order, and may choose another order when the
same expression is evaluated again.There is no concept of left-to-right or right-to-left evaluation in
C++. This is not to be confused with left-to-right and right-to-left
associativity of operators: the expression a() + b() + c() is parsed
as (a() + b()) + c() due to left-to-right associativity of operator+,
but the function call to c may be evaluated first, last, or between
a() or b() at run time
In your line
cout << sum(3) << sum(2)
the order of the two operator<<
calls depends on the operator you use (here <<
so left-to-right), but the evaluation of each subexpression, namely sum(3)
and sum(2)
has no defined order and depends on the mood (most optimized compile approach usually) of your compiler.
For info here is a list of operators associativity: https://en.cppreference.com/w/cpp/language/operator_precedence
Called a function with cout statement inside a cout statement
The order of evaluation of arguments to a function is unspecified. Your line looks like this to the compiler:
operator<<(operator<<(operator<<(cout, "The Lucky "), print()), endl);
The primary call in the statement is the one with endl as an argument. It is unspecified whether the second argument, endl, is evaluated first or the larger sub-expression:
operator<<(operator<<(cout, "The Lucky "), print())
And breaking that one down, it is unspecified whether the function print()
is called first, or the sub-expression:
operator<<(cout, "The Lucky ")
So, to answer your question:
What causes this behavior? Does this has to do with C++ standard or its behavior vary from one compiler to another?
It could vary from compiler to compiler.
Order of evaluation of arguments using std::cout
The evaluation order of elements in an expression is unspecified (except some very particular cases, such as the &&
and ||
operators and the ternary operator, which introduce sequence points); so, it's not guaranteed that test
will be evaluated before or after foo(test)
(which modifies it).
If your code relies on a particular order of evaluation the simplest method to obtain it is to split your expression in several separated statements.
call function with cout inside a cout statement
This seems to be a very common misunderstanding among beginners. Printing something via cout
is not the same as returning a value from a function. Thats completely orthogonal things.
You can write:
std::string returned_value = get_something();
std::cout << returned_value;
But you cannot write:
??? returned_value = print_something();
std::cout << returned_value;
because print_something()
does not return anything! void
denotes the absence of a type. You cannot have an object of type void
.
On the other hand, when you call a function, you can use the returned value (above), or you can ignore it, so this is correct code:
print_something(); // prints something
get_something(); // also print something and returned value is ignored
Note that the function get_something
should get a better name, because it is not just "getting" a value. How about print_and_return_something()
?
PS:
What I am really confused about is that, how is it possible to do a cout after a cout? Am I just missing what cout actually does?
Not sure If I understand, but I will try... std::cout
is an object of type std::ostream
. It has an operator<<
that you can call, similar to calling methods of other objects. The following two are identical and just use different syntax:
std::cout.operator<<( "Hello World");
std::cout << "Hello World";
When you call print_something()
then first the function is executed, then the return value is returned to the caller and execution continues with the caller. This:
std::cout << get_something();
is more or less the same as (well, its a crude simplification, but should be ok here):
// inside get_something
std::cout << "output something";
// return value
std::string result{"output something"};
// now execution continues in caller
std::cout << result;
Calling cout
after cout
is no different from calling some other function. Suppose you have a function print()
that prints something then you can write
std::string print_and_return() {
std::string x{"Hello World"};
print(x);
return x;
}
The caller can do
std::string x = print_and_return(); // <- this already calls print()
print(x); // now we call it again
This is more or less the same as yours, just that I used some hypothetical print()
instead of std::cout::operator<<
.
How object cout prints multiple arguments?
IOStreams only take one argument at a time, so it works just fine. :)
The magic of operator overloading means that this:
std::cout << a << b << c;
is actually this:
std::operator<<(std::operator<<(std::operator<<(std::cout, a), b), c);
or this:
std::cout.operator<<(a).operator<<(b).operator<<(c);
(Depending on the types of a
, b
and c
, either a free function or a member function will be invoked.)
and each individual call is to an overload that accepts the type you give it. No argument-counting or format strings required, as they are with your single calls to printf
.
How to print function pointers with cout?
There actually is an overload of the << operator that looks something like:
ostream & operator <<( ostream &, const void * );
which does what you expect - outputs in hex. There can be no such standard library overload for function pointers, because there are infinite number of types of them. So the pointer gets converted to another type, which in this case seems to be a bool - I can't offhand remember the rules for this.
Edit: The C++ Standard specifies:
4.12 Boolean conversions
1 An rvalue of arithmetic,
enumeration, pointer, or pointer to
member type can be converted to an
rvalue of type bool.
This is the only conversion specified for function pointers.
Function that prints something to std::ostream and returns std::ostream?
You can't fix the function. Nothing in the spec requires a compiler to evaluate a function call in an expression in any particular order with respect to some unrelated operator in the same expression. So without changing the calling code, you can't make MyPrint()
evaluate after std::cout << "Value: "
Left-to-right order is mandated for expressions consisting of multiple consecutive << operators, so that will work. The point of operator<< returning the stream is that when operators are chained, the LHS of each one is supplied by the evaluation of the operator to its left.
You can't achieve the same thing with free function calls because they don't have a LHS. MyPrint()
returns an object equal to std::cout
, and so does std::cout << "Value: "
, so you're effectively doing std::cout << std::cout
, which is printing that hex value.
Since the desired output is:
Value: 12
the "right" thing to do is indeed to override operator<<. This frequently means you need to either make it a friend, or do this:
class WhateverItIsYouReallyWantToPrint {
public:
void print(ostream &out) const {
// do whatever
}
};
ostream &operator<<(ostream &out, const WhateverItIsYouReallyWantToPrint &obj) {
obj.print(out);
}
If overriding operator<<
for your class isn't appropriate, for example because there are multiple formats that you might want to print, and you want to write a different function for each one, then you should either give up on the idea of operator chaining and just call the function, or else write multiple classes that take your object as a constructor parameter, each with different operator overloads.
Related Topics
What Does 'Unsigned Temp:3' in a Struct or Union Mean
How to Create a Dynamic Array of Integers
Good Input Validation Loop Using Cin - C++
Alternative to Itoa() For Converting Integer to String C++
Do Built-In Types Have Default Constructors
Why Do I Get an Infinite Loop If I Enter a Letter Rather Than a Number
What Are Access Specifiers? Should I Inherit With Private, Protected or Public
Why Doesn't a Simple "Hello World"-Style Program Compile With Turbo C++
Is Std::Vector So Much Slower Than Plain Arrays
Unicode Encoding For String Literals in C++11
Does "Int Size = 10;" Yield a Constant Expression
C++ "Virtual" Keyword For Functions in Derived Classes. Is It Necessary
What Are the Differences Between C-Like, Constructor, and Uniform Initialization
How to Get and Use the Header File ≪Graphics.H≫ in My C++ Program