Why calling address-of operator on rvalues compiles? - c++

AFAIK it is illegal to take the address of an rvalue because the address-of operator & takes an lvalue and returns the address of the object's called on address.
Here is an example I've tried to understand but find it a bit confusing:
#include <deque>
#include <iostream>
int main() {
using std::cout;
using std::endl;
std::deque<int> di{ 1, 1, 2, 3, 5, 8, 13 };
std::deque<int>::iterator it = di.end() - 1;
cout << *it << endl;
cout << &it-- << endl; // is it UB?
cout << *it << endl;
cout << &it-- << endl;
cout << *it << endl;
cout << &it-- << endl;
cout << *it << endl << endl;
cout << &--it << endl; // ok
cout << *it << endl; // ok
cout << &--it << endl; // ok
cout << *it << endl; // ok
std::cout << std::endl << "done!" << std::endl;
}
In the lines where I've used the pre-decrement operator it is OK because this operator and & have the same precedence level and are evaluated from right-to-left (RL) thus -- evaluates first and it returns an lvalue (takes also lvalue). then & is evaluated so & on an lvalue is OK.
The problem above in the post-decrement operator which takes an lvalue and returns an rvalue and has higher precedence over &. So in these expressions I am calling & on rvalue which is normally not allowed. But why the code compile and gives different results (addresses)??
When compiled on Wandbox with flag -pedantic it doesn't compile:
prog.cc:25:17: error: taking address of rvalue [-fpermissive]
25 | cout << &offEnd-- << endl; // -- has higher precedence than & thus this expression decrements offEnd and returns a copy of original of offEnd then print the address of this original object (before decrementing it)
Also on MSVC++14 with /Wall.
So is it undefined behavior in my code?
so why C++ allowed calling address of operator & on rvalue while the standard disallows it?
Finally I want to know where theses different addresses come from in such expression: std::cout << &it-- << std::endl;? But the values of de-referencing are correct!

Related

C++ unique_ptr; Why this sample codes get compile error?? error codes are so long that I can't specify it

I'm studying about smart pointer now, and I just built the sample codes in the book.
But when I use unique_ptr like this code below, it makes compile error. The error codes are so long that they are almost cut, so I can't write down them all.
I wonder why this codes got error... please help me.
compiler and OS : g++ (Ubuntu 9.1.0-2ubuntu2~18.04) 9.1.0
error codes that i could found
/workspace/What_I_Learned/Cpp/53/53-4.cpp:23:30: error: no match for ‘operator<<’ (operand types are ‘std::basic_ostream<char>’ and ‘std::unique_ptr<int>’)
23 | cout << "smart pointer 2: " << p2 << '\n';
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^~ ~~
| | |
| std::basic_ostream<char> std::unique_ptr<int>
/usr/include/c++/9/ostream:691:5: error: no type named ‘type’ in ‘struct std::enable_if<false, std::basic_ostream<char>&>’
codes i wrote down
#include <iostream>
#include <memory>
using namespace std;
int main(void) {
unique_ptr<int> p1(new int(10));
unique_ptr<int> p2;
cout << "smart pointer 1: " << p1 << '\n';
cout << "smart pointer 2: " << p2 << '\n';
cout << "move to p2\n";
p2 = move(p1);
cout << "smart pointer 1: " << p1 << '\n';
cout << "smart pointer 2: " << p2 << '\n';
cout << "free memory\n";
p2.reset();
cout << "smart pointer 1: " << p1 << '\n';
cout << "smart pointer 2: " << p2 << '\n';
}
I already tried -std=g++11 and -std=g++14.
There is no operator << for an object of the type std::unique_otr.
If you need to output the value of the owned pointer then write
cout << "smart pointer 1: " << p1.get() << '\n';
If the template argument of the class template std::unique_ptr is char then you need to cast the returned expression of the member function get to the type void *. For example
cout << "smart pointer 1: " << static_cast<void *>( p1.get() ) << '\n';
Here is a demonstrative program.
#include <iostream>
#include <memory>
int main()
{
std::unique_ptr<int> p1(new int( 10 ) );
std::unique_ptr<char> p2( new char( 'A') );
std::cout << "smart pointer 1: " << p1.get() << '\n';
std::cout << "smart pointer 2: " << static_cast<void *>( p2.get() ) << '\n';
}
The program output might look like
smart pointer 1: 0x5593824d6e70
smart pointer 2: 0x5593824d6e90
If the owned pointer of an object of the type std::unique_ptr<char> is outputted without casting then it will be outputted as a C string instead of outputting its stored value (address).
If you need to output the pointed value of an object of the class template std::unique_ptr then just apply the dereference operator.
For example
cout << "smart pointer 1: " << *p1 << '\n';
Here is a demonstrative program
#include <iostream>
#include <memory>
int main()
{
std::unique_ptr<int> p1(new int( 10 ) );
std::unique_ptr<char> p2( new char( 'A') );
std::cout << "the value of the smart pointer 1: " << *p1 << '\n';
std::cout << "the value of the smart pointer 2: " << *p2 << '\n';
}
The program output is
the value of the smart pointer 1: 10
the value of the smart pointer 2: A
Before outputting a pointed value you can check whether the object of the class template std::unique_ptr does not store a null pointer like
if ( p1 )
{
std::cout << "the value of the smart pointer 1: " << *p1 << '\n';
}
if ( p2 )
{
std::cout << "the value of the smart pointer 2: " << *p2 << '\n';
}
Your are passing the unique_ptr object to cout which wont know what to do with it as there is no appropriate overload available. If you want the pointer value to be printed then you need to do it like this:
std::cout << "P: " << (void *)p1.get() << std::endl;
If you want to print the value, that it points to, you can of course do it like this:
std::cout << "*P: " << *p1 << std::endl;
But in case of p2 you will dereference a nullptr which is invalid causing undefined behavior.
The error message tells you that there is no operator << overload for a std::unique_ptr. What you can do instead is
std::cout << "smart pointer dereferenced: " << *p1 << '\n';
Note that this is undefined behaviour if the smart pointer is in its null state.
As a side note, consider using std::make_unique<int>(42) to initialize a std::unique_ptr (if C++14 is available), as it encapsulates the raw new.

C++ ostream << overloading problems

We know that the fascinating class iostream is something too powerful.
it has overloded the insertion operator "<<" to take many datatypes:
ostream& operator(ostream&, int),
ostream& operator(ostream&, char)...
we cannot instantiaate ostream: ostream print;
because ostream because its most CTORSs are "protected-socoped" (cannot be accessed from outside).
the only Constructor we can call is ostream(streambuf*) which takes a pointer to another class object ( class streambuf);
I just wanted to mess up with this class:
#include <ostream>
using namespace std;
int operator << (ostream& out, int* x)
{
out << "invoked!" << endl;
cout << *x; // works well!
cout << x; // normally works well and it prints the address that x points to but instead the program get in infinite loop or crushes!
return *x;
}
int main()
{
system("color 1f");
int* pVal = new int(57);
cout << *pVal << endl;
int* pX = new int(7);
cout << *pX << endl;
cout << *pVal << ", " << *pX << endl;
//cout << pVal << endl; // this doesn't work because my operator returns
//int and not a reference to ostream.
// and it is equal to: 0 << endl; which generates the same error
cout << pVal; // this works
// cout << endl << endl << endl;
return 0;
}
I overloaded the insertion operator to take an lvalue as a reference to an ostream object and a pointer to int as rvalue, I popup a message inside my function to get sure that it is invoked.
Note that I intentionally overloaded it to return int value so that no one can write:
out << pInt << *pInt << endl;
... but just:
out << pInt;
My problem, as you can see in the inline-comments above, is that whilst cout << x normally works well, instead the program get in infinite loop or crushes!
return *x;
Can anyone explain why I am getting the error?
The problem hapens because if you just cout << x, it will call your overloaded function over and over. It never returns.
Here's the solution (cast x to void*)
int operator << (ostream& out, int* x)
{
out << "invoked!" << endl;
cout << *x; // works well!
cout << (void*)x;
return *x;
}

Random Number Order in C++ using <random>

I have the following code, that I wrote to test a part of a larger program :
#include <fstream>
#include <random>
#include <iostream>
using namespace std ;
int main()
{
mt19937_64 Generator(12187) ;
mt19937_64 Generator2(12187) ;
uniform_int_distribution<int> D1(1,6) ;
cout << D1(Generator) << " " ;
cout << D1(Generator) << " " << D1(Generator) << endl ;
cout << D1(Generator2) << " " << D1(Generator2) << " " << D1(Generator2) << endl ;
ofstream g1("g1.dat") ;
g1 << Generator ;
g1.close() ;
ofstream g2("g2.dat") ;
g2 << Generator2 ;
g2.close() ;
}
The two generators are seeded with the same value, and therefore I expected the second row in the output to be identical to the first one. Instead, the output is
1 1 3
1 3 1
The state of the two generators as printed in the *.dat files is the same. I was wondering if there might be some hidden multi-threading in the random number generation causing the order mismatch.
I compiled with g++ version 5.3.0, on Linux, with the flag -std=c++11.
Thanks in advance for your help.
x << y is syntactic sugar for a function call to operator<<(x, y).
You will remember that the c++ standard places no restriction on the order of evaluation of the arguments of a function call.
So the compiler is free to emit code that computes x first or y first.
From the standard: §5 note 2:
Operators can be overloaded, that is, given meaning when applied to expressions of class type (Clause
9) or enumeration type (7.2). Uses of overloaded operators are transformed into function calls as described
in 13.5. Overloaded operators obey the rules for syntax specified in Clause 5, but the requirements of
operand type, value category, and evaluation order are replaced by the rules for function call.
That's because the order of evaluation of this line
cout << D1(Generator2) << " " << D1(Generator2) << " " << D1(Generator2) << endl ;
is not what you think.
You can test it with this:
int f() {
static int i = 0;
return i++;
}
int main() {
cout << f() << " " << f() << " " << f() << endl ;
return 0;
}
Output: 2 1 0
The order is not specified by the C++ standard, so the order could be different on other compilers, please see Richard Hodges' answer.
A slight change to the program reveals what happens:
#include <fstream>
#include <random>
#include <iostream>
using namespace std ;
int main()
{
mt19937_64 Generator(12187) ;
mt19937_64 Generator2(12187) ;
uniform_int_distribution<int> D1(1,100) ;
cout << D1(Generator) << " " ;
cout << D1(Generator) << " " ;
cout << D1(Generator) << endl ;
cout << D1(Generator2) << " " << D1(Generator2) << " " << D1(Generator2) << endl ;
}
Output:
4 48 12
12 48 4
So your Generators produce equal results - but the order the arguments of your cout-line are calculated in different order.
Try it online:
http://ideone.com/rsoqDe
These lines
cout << D1(Generator) << " " ;
cout << D1(Generator) << " "
<< D1(Generator) << endl ;
cout << D1(Generator2) << " "
<< D1(Generator2) << " "
<< D1(Generator2) << endl ;
because D1() returns an int, for which ostream::operator<<() has an overload, are effectively calling (excluding endl)
cout.operator<<(D1(Generator));
cout.operator<<(D1(Generator))
.operator<<(D1(Generator));
cout.operator<<(D1(Generator2))
.operator<<(D1(Generator2))
.operator<<(D1(Generator2));
Now, the standard has this to say,
§ 5.2.2 [4]
When a function is called, each parameter shall
be initialized with its corresponding argument.
[ Note: Such initializations are indeterminately sequenced with respect to each other — end note ]
If the function is a non-static
member function, the this parameter of the function shall be
initialized with a pointer to the object of the call
So let's break down the preceding expression
cout.operator<<(a()) // #1
.operator<<(b()) // #2
.operator<<(c()); // #3
To illustrate the construction of the this pointer, these are conceptually equivalent to (omitting ostream:: for brevity):
operator<<( // #1
&operator<<( // #2
&operator<<( // #3
&cout,
a()
), // end #3
b()
), // end #2
c()
); // end #1
Now let's look at the top-level call. Which do we evaluate first, #2, or c()? Since, as emphasized in the quote, the order is indeterminate, then we don't know—and this is true recursively: even if we evaluated #2, we would still face the question of whether to evaluate its internal #3 or b().
So that hopefully explains what's going on here more clearly.

C++ Rvalue arrgument and move

Trying to understand the difference between rvalue formal parameter and call by value parameter.
When I called fun(move(Demo{}) I see only default constructor called once.
While I called gun(move(Demo{}) I see default constructor and rval constructor called. Please some one help me to understand the behaviour of && formal argument type, uses of && in functions/member functions.
compilers clang++ , g++ , vc++
#include <iostream>
#include <utility>
#include <type_traits>
using namespace std;
class Demo {
int i = 10;
public:
Demo(){
i = 40;
}
Demo(Demo && p) {
i = p.i + 20;
cout << "I am in Demo && " << endl;
}
Demo & operator = (Demo & p) {
cout << "I am in operator && " << endl;
}
Demo & operator = (Demo && p) {
i = p.i + 10;
cout << "I am in operator && " << endl;
}
~Demo(){
cout << "I am in ~Demo " << i << endl;
}
};
void fun(Demo & d) {
cout << "fun( &) " << endl;
cout << " -- End -- " << endl;
}
void fun(Demo && d) {
cout << "fun( && ) " << endl;
std::cout << std::boolalpha;
cout << "Lvalur reference : " << is_lvalue_reference<decltype(d)>::value << endl;
cout << "Rvalue Refernce : " << is_rvalue_reference<decltype(d)>::value << endl;
cout << " -- End -- " << endl;
}
void gun(Demo d) {
cout << "gun( ) " << endl;
std::cout << std::boolalpha;
cout << "Lvalur reference : " << is_lvalue_reference<decltype(d)>::value << endl;
cout << "Rvalue Refernce : " << is_rvalue_reference<decltype(d)>::value << endl;
cout << " -- End -- " << endl;
}
int main() {
cout << "Main begin " << endl;
fun(move(Demo{}));
cout << "------------------- " << endl;
gun(move(Demo{}));
cout << "Main End " << endl;
}
//Output
Main begin
fun( && )
Lvalur reference : false
Rvalue Refernce : true
-- End --
I am in ~Demo 40
-------------------
I am in Demo &&
gun( )
Lvalur reference : false
Rvalue Refernce : false
-- End --
I am in ~Demo 60
I am in ~Demo 40
Main End
Short answer: an rvalue reference behaves mainly like an usual non-const reference (i mean, a non-const lvalue reference) and in your code it's basically the same as providing lvalue references instead of rvalue references (set aside the traits which differentiate them).
The difference is that when you pass an rvalue reference to a function/method you're telling it "i won't use that anymore, go ahead, do anything you want with it".
Longer answer: rvalue references appeared because you can initialize or assign objects with temporaries, but without them you had to:
- build a temporary
- pass a const reference of the temporary to the methof/function
- clear the muting object
- sometimes reallocate memory to hold the temporary's contents
- copy the temporary's contents
- destroy the temporary
In short, we were performing an unneeded (and potentially expensive) copy whereas we could have simply "moved" the ownership of the temporary's contents to the muted object (when possible).
Rvalue references were introduced so that we could have a type to represent objects in the end of their lifetime which can be freely modified because they won't be used any further anyway.
They are noted with && (not to be mistaken for "universal references" which also use && in a template deduction context).
The difference between passing by value and passing by rvalue reference is that passing value will call the copy constructor and provide you with a fresh instance of that object, whereas passing by rvalue reference (as i said before) behaves exactly the same as passing an usual non-const reference.
However, we don't use usual non-const references because they don't have the "same semantics" and that it would be problematic if a constructor mistook our lvalue reference for an rvalue reference and thrashed our object with its move constructor while we intended to use the copy constructor.

c++11 capture-by-value lambda producing wrong value

I'm trying to store a lambda in an object system involving several layers of indirection. I'm using g++ 4.7.1.
Depending on how exactly I construct the (equivalent) objects, the lambda may or may not have the correct value.
Code:
#include <iostream>
#include <functional> // used for std::function
using namespace std; // TODO nope
typedef function<int()> intf;
struct SaveLambda {
const intf func;
SaveLambda(const intf& _func) : func(_func) {}
};
struct StoreSaved {
const SaveLambda* child;
StoreSaved(const SaveLambda& _child) : child(&_child) {
cout << "Before returning parent: " << child->func() << endl;
}
};
int main() {
const int ten = 10;
auto S = SaveLambda([ten](){return ten;});
cout << "No indirection: " << S.func() << endl << endl;
auto saved = StoreSaved(S);
cout << "Indirection, saved: " << saved.child->func() << endl << endl;
auto temps = StoreSaved ( SaveLambda([ten](){cout << "&ten: "<< &ten << endl; return ten;}) );
cout << "***** what. *****" << endl;
cout << "Indirection, unsaved: " << temps.child->func() << endl;
cout << "***** what. *****" << endl << endl;
cout << "ten still lives: " << ten << endl;
}
Compile as g++ -std=c++11 -Wall -o itest itest.cpp and run: notice the one line of output with a different value.
What am I doing wrong? I assumed that capture-by-value would, well, capture by value. (Observe most disconcertingly that the print in StoreSaved (line 15) produces the correct value, unlike line 34, despite these both referring to the same object. The only difference is adding another layer of indirection.)
This is wrong:
auto temps = StoreSaved(
/* This temporary value dies at the last semicolon! */
SaveLambda([ten](){cout << "&ten: "<< &ten << endl; return ten;})
);
StoreSaved then has a pointer to a nonexistent object. Using it is UB.
As already pointed out by others, the problem is that in temps you end with a pointer to a nonexistent SaveLambda struct, as it is a temporary.
You can keep a copy using a SaveLambda struct in StoreSaved, instead of a pointer:
struct StoreSaved {
const SaveLambda child;
StoreSaved(const SaveLambda& _child) : child(_child) {
cout << "Before returning parent: " << child.func() << endl;
}
};
You also have to change all the child->func() to child.func(), as you are not dealing with a pointer anymore.