Why if we pass a class field pointer int* value in a lambda, then doesn't change value?
struct A {
A() {
auto f = [](int* value) {
value = new int(0);
};
f(value);
}
int* value = new int(42);
};
int main()
{
A obj{};
std::cout << *(obj.value) << std::endl;
}
Changes made to a function parameter are not visible to the caller, unless you take it by reference.
In your case, you would simply need to do
auto f = [](int* &value) {
value = new int(0);
};
Now changes to the parameter value are reflected in the member value.
Note that in your example, (without the reference), the compiler would warn that you are setting value but not using it.
Also, this might solve the specific question, but you are still leaking memory here.
your code isn't compilable - you cannot assign int* to int here: value = int(0);.
I have tried your code with fixed mentioned error:
struct A {
A() {
auto f = [](int* value) {
*value = int(0); // here value is being changed as expected
};
f(value);
}
int* value = new int(42);
};
int main()
{
A obj{};
std::cout << *(obj.value) << std::endl;
}
Everything works fine - passed value pointer to the f lambda is being changed from 42 to 0 value after constructor of struct is called.
Related
How should be the signature of a funtion
in order to not be able able to change
both the value and the address of the passed pointer?
void testP(int*& k)
{
std::cout << "testP addr:" << k << std::endl;
}
int main()
{
int* p = new int(5);
testP(p);
delete p;
return 0;
}
How should be the signature of a funtion in order to not be able able to change both the value and the address of the passed pointer?
You need to make the parameter to be a reference to a const pointer to a const int as shown below:
//---------vvvvv-----vvvvv----------->added const
void testP(const int*const& k);
{
//*k = 4; //NOT ALLOWED
// k = nullptr ; //NOT ALLOWED
}
Note that the parameter k in the above declaration will be the same if you change the parameter declaration to int const* const&.
I wanted to undersatnd variable i scope w.r.to lambda function.
i is captured as by value So incrementation should only happen internally and it should not effect the global i value. So i expected output 1 1 1. But the output is 1 2 2
int i = 0;
auto a = [i]() mutable { cout << ++i << endl; };
a(); // i copies by value , So i value get changed internally in lambda function scope
auto b = a;
a(); // here why it is giving 2 instead of 1 ???
b();
What am i missing here ?
int i = 0;
auto a = [i]() mutable { cout << ++i << endl; }; // i is captured in a with value 0
a(); // i captured by a becomes 1
auto b = a; // b is copied from a, the captured i in b is copied with value 1 too
a(); // i captured by a becomes 2
b(); // i captured by b becomes 2
Result of lambda expression is an object with operator(). Code here
int i = 0;
auto a = [i]() mutable { cout << ++i << endl; };
a();
a();
results in behaviour roughly similar to this:
int i = 0;
struct local_lambda_01 {
private: // some older compilers skip this and in result there is an
// implementation detail that you can access following members
int i = ::i; // this is result of capture by value.
public:
void operator() { // it's not `const` because lambda is `mutable`
cout << ++i << endl; // it's `this->i`
}
} a; // a variable of local_lambda_01 type;
a(); // call to operator(), increments member i of local_lambda_01
a();
A copy of variable i's value was stored at point of creation of callable a instance. As lambda was declared mutable, operator() is not const-declared and can modify stored values. It doesn't change the original.
If we add statement
auto b = a;
after calling a(), we perform copy on already modified instance of the object.
#include<iostream>
using namespace std;
class Test
{
private:
int x;
public:
Test(int x = 0) { this->x = x; }
void change(Test *t)
{
this = t; //line 1
}
void print() { cout << "x = " << x << endl; }
};
int main()
{
Test obj(5);
Test *ptr = new Test (10);
obj.change(ptr);
obj.print();
return 0;
}
since we know that this pointer hold the reference of calling object. In line 1 i am trying to change the reference of calling object but it shows an error "lvalue required". Can someone explain this??
You cannot assign a pointer to this pointer, because it's a prvalue.
this pointer is a constant pointer that holds the memory address of the current object.
As a result, this is of type const Test* in your case, so it cannot be assigned to. Doing so (if it was allowed) would effectively allow an object to change its own address in memory, as #Peter mentioned.
Note: const Test* is a pointer to a constant object. The object it points to is constant, not the pointer itself.
PS: this->x = t->x; is probably what you meant to say.
Here you are assigning a pointer(here t) to "this" pointer for a particular object.
"this" pointer is const. pointer that holds the memory address of the current object. You simply can't change the this pointer for an object, since doing this you will practically be changing the location of the object in the memory keeping the name same.
Reference - ‘this’ pointer in C++
#include <iostream>
using namespace std;
class Test
{
private:
int x;
public:
Test(int x=0)
{
this->x = x;
}
void change(Test *t)
{
t->x; //t is a pointer. so make it point to x
}
void print() { cout << "x = " << x << endl; }
};
int main()
{
Test obj(5);
Test obj1(10); //create a new object
Test *ptr = &obj1;//make the pointer point to obj1
obj.change(ptr); //use change() to point to argument of obj1
obj.print(); //print the value of obj now
return 0;
}
When you have a function like this, the formal parameter is a reference, it becomes another name for the actual argument, so that when we modify the formal parameter inside the function, the original variable outside the function is changed.
void add_five(int& a)
{
a += 5;
}
int main()
{
int number = 3;
add_five(number);
std::cout << number << std::endl; // prints 8
return 0;
}
I have some code which works on a linked lists. And I am passing two Node*s into the function.
void LinkedList::move_five_nodes(Node* ptr1, Node* ptr2) { ... }
...
void LinkedList::anotherFunction()
{
Node* leader;
Node* trailer;
...
move_five_nodes(leader, trailer);
...
}
I think that the rvalues memory addreses inside the leader and trailer pointer variables will be assigned into the Node* lvalues ptr1 and ptr2.
Node* ptr1 = leader;
Node* ptr2 = trailer;
The issue is that ptr1 and ptr2 are independent local variables inside the function. Initially, they point to the same place as the actual argument pointers. However, my function moves some nodes, and at the end of the function, the values of ptr1 and ptr2 are changed. I want these changes to also be in the original variables leader and trailer, just like references. So even when ptr1 and ptr2 expire, leader and trailer should go into their positions.
How would I do this? Maybe type cast the pointers into int&? Or maybe use pointers to pointers? I want to pass a pointer by reference, but I'm not sure how to do that.
I want to pass a pointer by reference, but I'm not sure how to do that.
For this, consider the following snippet
#include <iostream>
void test(int*& t)
{
t = nullptr;
}
int main()
{
int* i = new int(4);
test(i);
if (i == nullptr)
std::cout << "I was passed by reference" << std::endl;
}
in which is is passed by reference to test, where it is set to nullptr and the program prints: I was passed by reference.
I think this example should make clear how to pass a pointer by reference to a function.
So in your case the function signiture must change to
void LinkedList::move_five_nodes(Node*& ptr1, Node*& ptr2) { ... }
#include <iostream>
void test(int& ref);
int main()
{
int* pointer = new int(10);
std::cout << "before" << *pointer << std::endl ;
test(*pointer);
std::cout << "after" << *pointer << std::endl;
delete pointer;
}
void test(int& ref)
{
ref = 20;
}
I stumbled upon something similar today, and subsequently tried a few things out and noticed that the following seems to be legal in G++:
struct A {
int val_;
A() { }
A(int val) : val_(val) { }
const A& operator=(int val) { val_ = val; return *this; }
int get() { return val_; }
};
struct B : public A {
A getA() { return (((A)*this) = 20); } // legal?
};
int main() {
A a = 10;
B b;
A c = b.getA();
}
So B::getB returns a type A, after it as assigned the value 20 to itself (via the overloaded A::operator=).
After a few tests, it seems that it returns the correct value (c.get would return 20 as one may expect).
So I'm wondering, is this undefined behavior? If this is the case, what exactly makes it so? If not, what would be the advantages of such code?
After careful examination, with the help of #Kerrek SB and #Aaron McDaid, the following:
return (((A)*this) = 20);
...is like shorthand (yet obscure) syntax for:
A a(*this);
return a.operator=(20);
...or even better:
return A(*this) = 20;
...and is therefore defined behavior.
There are a number of quite separate things going on here. The code is valid, however you have made an incorrect assumption in your question. You said
"B::getA returns [...] , after it as assigned the value 20 to itself"
(my emphasis) This is not correct. getA does not modify the object. To verify this, you can simply place const in the method signature. I'll then fully explain.
A getA() const {
cout << this << " in getA() now" << endl;
return (((A)*this) = 20);
}
So what is going on here? Looking at my sample code (I've copied my transcript to the end of this answer):
A a = 10;
This declares an A with the constructor. Pretty straightfoward. This next line:
B b; b.val_ = 15;
B doesn't have any constructors, so I have to write directly to its val_ member (inherited from A).
Before we consider the next line, A c = b.getA();, we must very carefully consider the simpler expression:
b.getA();
This does not modify b, although it might superfically look like it does.
At the end, my sample code prints out the b.val_ and you see that it equals 15 still. It has not changed to 20. c.val_ has changed to 20 of course.
Look inside getA and you see (((A)*this) = 20). Let's break this down:
this // a pointer to the the variable 'b' in main(). It's of type B*
*this // a reference to 'b'. Of type B&
(A)*this // this copies into a new object of type A.
It's worth pausing here. If this was (A&)*this, or even *((A*)this), then it would be a simpler line. But it's (A)*this and therefore this creates a new object of type A and copies the relevant slice from b into it.
(Extra: You might ask how it can copy the slice in. We have a B& reference and we wish to create a new A. By default, the compiler creates a copy constructor A :: A (const A&). The compiler can use this because a reference B& can be naturally cast to a const A&.)
In particular this != &((A)*this). This might be a surprise to you. (Extra: On the other hand this == &((A&)*this) usually (depending on whether there are virtual methods))
Now that we have this new object, we can look at
((A)*this) = 20
This puts the number into this new value. This statement does not affect this->val_.
It would be an error to change getA such that it returned A&. First off, the return value of operator= is const A&, and therefore you can't return it as a A&. But even if you had const A& as the return type, this would be a reference to a temporary local variable created inside getA. It is undefined to return such things.
Finally, we can see that c will take this copy that is returned by value from getA
A c = b.getA();
That is why the current code, where getA returns the copy by value, is safe and well-defined.
== The full program ==
#include <iostream>
using namespace std;
struct A {
int val_;
A() { }
A(int val) : val_(val) { }
const A& operator=(int val) {
cout << this << " in operator= now" << endl; // prove the operator= happens on a different object (the copy)
val_ = val;
return *this;
}
int get() { return val_; }
};
struct B : public A {
A getA() const {
cout << this << " in getA() now" << endl; // the address of b
return (((A)*this) = 20);
// The preceding line does four things:
// 1. Take the current object, *this
// 2. Copy a slice of it into a new temporary object of type A
// 3. Assign 20 to this temporary copy
// 4. Return this by value
} // legal? Yes
};
int main() {
A a = 10;
B b; b.val_ = 15;
A c = b.getA();
cout << b.get() << endl; // expect 15
cout << c.get() << endl; // expect 20
B* b2 = &b;
A a2 = *b2;
cout << b2->get() << endl; // expect 15
cout << a2.get() << endl; // expect 15
}