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
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!
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.
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.
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)
{
}