C++ Rvalue arrgument and move - c++

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.

Related

How to catch the address of the functor generated for a lamda expression?

you know that the compiler transforms a lambda expression into some kind of functor:
the captured variables become data members of this functor. Variables captured by value are copied into data members of the functor. These data members have the same constness as the captured variables et cetera...
Now I wonder if it's possible to catch the address of this hidden object generated from the compiler behind the scenes
I give you a simple snippet of (WRONG) code just to show my intentions:
#include <iostream>
using namespace std;
class MetaData
{
public:
void printAddress()
{
cout << "\n printAddress:Instance of MetaData at &" << this;
}
};
int main()
{
MetaData md1;
cout << "\n &md1 = " << &md1 << "\n";
md1.printAddress();
cout << "\n\n--------------------\n\n";
int i = 5;
auto x = [i]() mutable {
//cout << "\n The address of the functor is &" << this; // ERROR ! ! !
cout << "\n Hello from Lambda ";
cout << "\n &i = " << &i << " ++i ==> " << ++i << endl; };
x(); // executing lambda
auto y = x; // y is constructed with copy ctor
y();
}
Link to Coliru
I'd like hidden functor to behave like MetaDatas.
Can someone clear my mind?
Thanks for your time.
Syntax would be:
auto x = [&](){ std::cout << &x; }; // but it is illegal too:
// variable 'x' declared with deduced type 'auto' cannot appear in its own initializer
Possible work-around is usage of Y-combinator, something like:
auto x = [i](auto& self) mutable {
cout << "\n The address of the functor is &" << &self;
cout << "\n Hello from Lambda ";
cout << "\n &i = " << &i << " ++i ==> " << ++i << endl; };
x(x); // executing lambda
Demo

Why calling address-of operator on rvalues compiles?

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!

Using references or pointers to perform a Deposit method?

I'm having trouble understanding passing references and pointers. I've gone over it so many times in my head but just can't seem to click with it, and I think it's what I need to use here, to actually modify the value in the Account object.
Are there any surefire simple ways to understand them? And how would they apply to this fairly simple scenario?
main code:
if (transactionMenuChoice == 2)
{
cout << "________________________________________________" << endl;
cout << "//TRANSACTION MENU - WITHDRAWAL" << endl;
cout << "//CURRENT CUSTOMER: " << allCustomers.at(customerIndex).getName() << endl;
cout << "//CURRENT ACCOUNT: " << allCustomers.at(customerIndex).getAccounts().at(accountIndex).getAccountNum() << " (" << allCustomers.at(customerIndex).getAccounts().at(accountIndex).getType() << ")" << endl;
cout << "||Withdraw how much?" << endl;
cout << "||£" << endl;
int d;
cin >> d;
allCustomers.at(customerIndex).getAccounts().at(accountIndex).removeFromBalance(d);
}
from my Account.cpp:
void Account::removeFromBalance(double d)
{
balance -= d;
}
Perhaps you are referring to the difference between value references and pointer references? A pointer is the address of a thing, not the thing itself. Your address is a 'pointer' to your mailbox, but not the mailbox itself. In your removeFromBalance function you are passing 'd' by value (not as a pointer). C++ object syntax can sometimes muddy the water since you will see '.' notation to call member function on actual (when you have an object) and '->' notation used to call a member function when you have a pointer to an object.

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.

Passing constructor arguments by value or by reference

Just a quick question about a function like this:
class Test {
public:
Test(vector<int>& v) {
v_ = v;
}
private:
std::vector<int> v_;
};
What's the difference between using Test(vector<int>& v) and Test(vector<int> v)? I seem to know that the first one should be faster since it is pass-by-reference. But I'm not so sure whether there are other differences.
The difference is that with Test(vector<int>& v) (which BTW is an lvalue reference) v refers to the original object, while with Test(vector<int> v) you have a copy. The following example code demonstrates the difference with an int and a normal function (note that for int, pass-by-value is actually faster!):
#include <iostream>
int global_i;
void pass_by_value(int i)
{
std::cout << "pass by value:\n";
std::cout << "initially: i = " << i << ", global_i = " << global_i << "\n";
i++;
std::cout << "after i++: i = " << i << ", global_i = " << global_i << "\n";
global_i++;
std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "\n";
}
void pass_by_reference(int& i)
{
std::cout << "pass by reference:\n";
std::cout << "initially: i = " << i << ", global_i = " << global_i << "\n";
i++;
std::cout << "after i++: i = " << i << ", global_i = " << global_i << "\n";
global_i++;
std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "\n";
}
void pass_by_const_reference(int const& i)
{
std::cout << "pass by const reference:\n";
std::cout << "initially: i = " << i << ", global_i = " << global_i << "\n";
// i++; not allowed!
// std::cout << "after i++: i = " << i << ", global_i = " << global_i << "\n";
global_i++;
std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "\n";
}
int main()
{
global_i = 1;
pass_by_value(global_i);
global_i = 1;
pass_by_reference(global_i);
global_i = 1;
pass_by_const_reference(global_i);
}
The output of this is:
pass by value:
initially: i = 1, global_i = 1
after i++: i = 2, global_i = 1
after global_i++: i = 2, global_i = 2
pass by reference:
initially: i = 1, global_i = 1
after i++: i = 2, global_i = 2
after global_i++: i = 3, global_i = 3
pass by const reference:
initially: i = 1, global_i = 1
after global_i++: i = 2, global_i = 2
As you see, with call by value, the argument and the passed variable are completely separate. Incrementing the argument does not change the passed variable, and incrementing the passed variable does not change the argument. On the other hand, with pass by reference, the argument just gives access to the passed variable: It doesn't matter which one you increment because effectively, they are the same. With pass by const reference, they are also the same, but you are not allowed to mosify the argument (there are ways around this, though). However, the argument still reflects any changes to the passed variable.
Those are the differences in functionality. However there are some more differences: For pass by value and pass by const reference, you can use an rvalue, like call_by_value(2) or call_by_const_reference(2). For call by value, it's obvious what happens: The argument gets the value 2, and that's it. However for const reference, there's an object expected (you could for example take the address of that object in the function). Therefore in that case a temporary object is created. For call by non-const reference, you cannot pass an rvalue.
C++11 adds another type to the mix, namely rvalue references. Those are denoted with && instead of &. Inside the function they behave exactly like normal (lvalue) references, but they differ in that they can be bound to rvalues, even if they are not const. Moreover, if you use them as return type, the call expression will be of rvalue type as if you had returned a value. Especially, you would not be able to pass the result of a function returning an rvalue reference to a function expecting an lvalue reference, just like you couldn't do that with the literal 2.
There are no rvalue references in your code, just a lot of unnecessary copying.
However, since we're on the topic, here's the right way to write this with move semantics:
Test(std::vector<int> v) // by value!
: v_(std::move(v))
{
}
In the pre-11 world, the next best way is to take the argument by const-reference and copy it:
Test(std::vector<int> const & v)
: v_(v)
{
}