confusions about mutable keyword in lambda expression - c++

In C++ Primer the book says if we want to change the variable captured by value, we should add "mutable" ketword behind the parameter list. However, I found some problems when I write some codes to test this rule.
First I write the codes below:
//case1:
int val = 5;
auto f1 = [val]() mutable {return ++val;};
cout << f1() <<endl;
//case2:
int val = 5;
auto f2 = [val]() mutable {return val+5;};
cout << f2() <<endl;
I get correct return value as expected. The first block of codes returns 6 and the second returns 10.
However, as I want to test whether the "mutable" keyword is really useful as descirbed in the book, I delete the "mutable" keyword in both blocks of codes.
//case1:
int val = 5;
auto f1 = [val]() {return ++val;};
cout << f1() <<endl;
//case2:
int val = 5;
auto f2 = [val]() {return val+5;};
cout << f2() <<endl;
As expected, case1 compilation failed. However, case2 can still compile success and return 10! I got confused and I don't know what happened behind the case2. From the case1, I see the "mutable" keyword really useful. However, from the case2, althougth there's not a "mutable", I can also change the value of the variable 'val'. Who can tell me what happened? Is there something I ignore?

int val = 5;
auto f1 = [val]() mutable {return ++val;};
cout << f1() <<endl;
is equivalent to:
int val = 5;
struct f1_t {
mutable int val;
f1_t(int v): val(v) {}
int operator()() const {return ++val;}
};
auto f1 = f1_t(val);
cout << f1() << endl;

++val is increasing val itself which would change val. But if you do val + 5, everything that happens is that a temporary int object of the value 10 is created and then returned, but val actually never changes so its perfectly valid.

Related

A pointer to const int in c++

In c++ I have the next code
int main() {
int i = 1;
cout<<"i = "<<i<<endl; //prints "i = 1"
int *iPtr = &i;
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 1"
(*iPtr) = 12; //changing value through pointer
cout<<"i = "<<i<<endl; //prints "i = 12"
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 12"
system("pause");
return 0;
}
Now the same code with constant integer i
int main() {
const int i = 1;
cout<<"i = "<<i<<endl; //prints "i = 1"
int *iPtr = (int*)&i; //here I am usint a type conversion
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 1"
(*iPtr) = 12; //changing value through pointer
cout<<"i = "<<i<<endl; //prints "i = 1"
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 12"
system("pause");
return 0;
}
As you can see, in second case with constant integer, there are two different values for *iPtr and const i, but the pointer *iPtr shows to constant i.
Please tell me what happens in the second case and why?
Your second code has undefined behavior. You can't change const data via a pointer-to-non-const. You are lucky your code didn't simply crash outright when trying to modify a read-only value.
In any case, the result you are seeing is because the compiler knows that i is const and has a value that is known at compile time. So the compiler is able to optimize away i in the cout statement and use 1 directly instead. That is why you see 1 when printing i and see 12 when printing *iPtr.
You are trying to remove the const qualifier of your variable.
In C++, you should use const_cast to do that.
However, const_cast can only be used in some precise circomstances: constness should only be removed from pointers/references to data which have been declared non-const at top level, otherwise the compiler may optimize the variable and modifying it through the pointer/reference would result in undefined behaviour.
For example, this is not legal :
const int i = 1;
const int *iPtr = &i;
int *iSuperPtr = const_cast<int*>(iPtr);
*iSuperPtr = 2; // Invalid : i is first declared const !!
But this is totally legal :
void modifyConstIntPtr(const int *iPtr) {
int *iSuperPtr = const_cast<int*>(iPtr);
*iSuperPtr = 2; // Valid : i is first declared non-const !!
}
void modifyConstIntRef(const int &iRef) {
int &iSuperRef = const_cast<int&>(iRef);
iSuperRef = 3; // Valid : i is first declared non-const !!
}
int main() {
int i = 1;
modifyConstIntPtr(&i);
std::cout << i << std::endl;
modifyConstIntRef(i);
std::cout << i << std::endl;
}
This aspect of C++ is well detailed here: https://stackoverflow.com/a/357607/3412316)

Trying to understand lambdas

Trying to understand lambdas in C++, what I do not understand is this:
int multiplier = 5;
auto timesFive = [multiplier](int a) { return a * multiplier; };
std::cout << timesFive(2) << '\n'; // Prints 10
multiplier = 15;
std::cout << timesFive(2) << '\n'; // Still prints 2*5 == 10 (???) - Should it be 30?
When the program calls the timesFive() the second time, I expect the result to be 30. But why is the result Still prints 2*5 == 10, not prints 2*15 == 30? Perhaps the lambda function somehow cannot track the value of multiplier, even though we have already tried to capture it?
And what is the way to get the desired result?
You captured multiplier by value, which means it was copied into the lambda. You need to capture it by reference:
int multiplier = 5;
auto timesFive = [&multiplier](int a) { return a * multiplier; };
std::cout << timesFive(2);
multiplier = 15;
std::cout << timesFive(2);
Lambdas are syntatic sugar for an unnamable class and the instance thereof. Sometimes expanding your code out to what this unnamable class can help understanding what is going on.
[ capture_list ]( arg_list ) -> return_value_clause_opt { body };
becomes very roughly (pseudo-code):
struct anonymous_type {
capture_list;
auto operator()( arg_list ) const -> return_value_clause_opt {
body
}
anonymous_type( capture_list_in ):capture_list(capture_list_in) {}
};
If you list a variable in capture_list by its plain name, it is copied into a copy within the anonymous class.
So your timesFive became
struct __secret_name__ {
int multiplier;
int operator()(int a) const { return a*multiplier; }
};
int multiplier = 5;
auto timesFive = __secret_name__{multiplier};
It should be pretty clear that changing multiplier in the above code won't change the behavior of timesFive.
If you put a & in front of the name, a non-const reference is placed within the anonymous class.
struct __secret_name__ {
int& multiplier;
int operator()(int a) const { return a*multiplier; }
};
int multiplier = 5;
auto timesFive = __secret_name__{multiplier};
now, changing multiplier will change the behavior of timesFive, because timesFive holds a reference to multiplier, not a copy of it.
Some details skipped above for brevity. The name __secret_name__ is only for exposition. The member variables of the lamba are not actually public. The lambda being trivially constructible is implementation defined even if its data is. Etc.

Confused by lambda output in this case

After learning lambda in C++11, I wrote this and got confused by the output.
auto f1 = [] () {
int tmp = 10;
int *tmp_p = &tmp;
return [tmp_p] (int x) {
return *tmp_p + x;
};
}();
auto f2 = []() {
int tmp = 10;
return [&tmp] (int x) {
return tmp + x;
};
}();
cout << f1(5) << endl;
cout << f1(5) << endl;
cout << f2(5) << endl;
cout << f2(5) << endl;
Output is:
15
5772973
2686617
2686617
What's the reason behind this?
Because undefined behavior.
tmp gets destructed after f1 is assigned, and so tmp_p becomes a dangling pointer. Anything can happen when you dereference it, including sometimes given the right value 15, and sometimes not 5772973.
The same goes for f2, but instead of using a pointer, you use a reference, which references a destructed object, which is also undefined behavior.
This is what we call undefined behavior. Why is your code causing undefined behavior?
First case: f1():
It's causing it, because after calling these lambdas the values of int tmp and int *tmp_p aren't on the stack anymore (the int *tmp_p was copied but the int tmp was removed).
Second case: f2(): The value of tmp was accessed by reference to the inner lambda. After the generating lambda finished it wasn't on the stack anymore and something obtained the memory and wrote garbage into it.

How/Can C++ lambdas retain inner state?

I have a basic lambda that looks like this:
auto l = [](){
int i = 0;
cout << i++;
}
Calling this a bunch of times, will keep printing 0. How can I retain i? Can I do this without functors?
Depending on what you want to do with this lambda, you might consider the following alternative:
auto exec = [i = 0]() mutable { cout << ++i << ' '; };
exec(); // 1
exec(); // 2
auto exec2 = exec; // copy state of lambda
exec2(); // 3
exec(); // 3
Using []() { static int i = 0; cout << ++i << ' '; }; instead will result in the sequence 1 2 3 4 being printed.
Live example
Try to think of a lambda as a class with an operator(). How would you retain state in a class? Have a member. Captures are the equivalent here.
#include <iostream>
auto l = [i=0]()mutable{
std::cout << i++;
};
auto l2=l;
int main(){
l(); // 0
l(); // 1
l(); // 2
l2(); // 0
l2(); // 1
l(); // 3
std::cout << '\n';
}
auto l = [](){
static int i = 0;
// ^^^^^^
cout << i++;
}
should fix your concerns.
In general functions cannot retain inner state without using a local static variable. There's no difference with using lambdas actually.
If you want to count copies, you can use an ordinary functor class implementation as #Revolver_Ocelot suggested.
If you want i to retain its value then you have three options:
Declare i as a global variable (Bad).
Pass previous value of i to the function every time (Better).
Declare i as a static variable (Best).
auto l = []() { static int i = 0; cout << i++ << endl; };
l(); l(); l();
This will give as output:
0
1
2

C/C++ changing the value of a const

I had an article, but I lost it. It showed and described a couple of C/C++ tricks that people should be careful. One of them interested me but now that I am trying to replicate it I'm not being able to put it to compile.
The concept was that it is possible to change by accident the value of a const in C/C++
It was something like this:
const int a = 3; // I promise I won't change a
const int *ptr_to_a = &a; // I still promise I won't change a
int *ptr;
ptr = ptr_to_a;
(*ptr) = 5; // I'm a liar; a is now 5
I wanted to show this to a friend but now I'm missing a step. Does anyone know what's missing for it to start compiling and working?
ATM I'm getting invalid conversion from 'const int*' to 'int*' but when I read the article I tried and it worked great.
you need to cast away the constness:
linux ~ $ cat constTest.c
#include <stdio.h>
void modA( int *x )
{
*x = 7;
}
int main( void )
{
const int a = 3; // I promisse i won't change a
int *ptr;
ptr = (int*)( &a );
printf( "A=%d\n", a );
*ptr = 5; // I'm a liar, a is now 5
printf( "A=%d\n", a );
*((int*)(&a)) = 6;
printf( "A=%d\n", a );
modA( (int*)( &a ));
printf( "A=%d\n", a );
return 0;
}
linux ~ $ gcc constTest.c -o constTest
linux ~ $ ./constTest
A=3
A=5
A=6
A=7
linux ~ $ g++ constTest.c -o constTest
linux ~ $ ./constTest
A=3
A=3
A=3
A=3
also the common answer doesn't work in g++ 4.1.2
linux ~ $ cat constTest2.cpp
#include <iostream>
using namespace std;
int main( void )
{
const int a = 3; // I promisse i won't change a
int *ptr;
ptr = const_cast<int*>( &a );
cout << "A=" << a << endl;
*ptr = 5; // I'm a liar, a is now 5
cout << "A=" << a << endl;
return 0;
}
linux ~ $ g++ constTest2.cpp -o constTest2
linux ~ $ ./constTest2
A=3
A=3
linux ~ $
btw.. this is never recommended... I found that g++ doesn't allow this to happen.. so that may be the issue you are experiencing.
Note any attempt to cast away constness is undefined by the standard. From 7.1.5.1 of the standard:
Except that any class member declared
mutable can be modified, any
attempt to modify a const object
during its lifetime
results in undefined behavior.
And right after this example is used:
const int* ciq = new const int (3); // initialized as required
int* iq = const_cast<int*>(ciq); // cast required
*iq = 4; // undefined: modifies a const object
So in short what you want to do isn't possible using standard C++.
Further when the compiler encounters a declaration like
const int a = 3; // I promisse i won't change a
it is free to replace any occurance of 'a' with 3 (effectively doing the same thing as #define a 3)
Just a guess, but a common question is why one can't convert an int** to a const int**, which at first appears to be reasonable (after all, you're just adding a const, which is normally ok). The reason is that if you could do this, you could accidentally modify a const object:
const int x = 3;
int *px;
const int **ppx = &px; // ERROR: conversion from 'int**' to 'const int**'
*ppx = &x; // ok, assigning 'const int*' to 'const int*'
*px = 4; // oops, just modified a const object
It's a very non-intuitive result, but the only way to make sure that you can't modify a const object in this case (note how there are no typecasts) is to make line 3 an error.
You're only allowed to add const without a cast at the FIRST level of indirection:
int * const *ppx = &px; // this is ok
*ppx = &x; // but now this is an error because *ppx is 'const'
In C++, it is impossible to modify a const object without using a typecast of some sort. You'll have to use either a C-style cast or a C++-style const_cast to remove the const-ness. Any other attempt to do so will result in a compiler error somewhere.
Back in the mists of time, we paleo-programmers used FORTRAN. FORTRAN passed all its parameters by reference, and didn't do any typechecking. This meant it was quite easy to accidentally change the value of even a literal constant. You could pass "3" to a SUBROUTINE, and it would come back changed, and so every time from then on where your code had a "3", it would actually act like a different value. Let me tell you, those were hard bugs to find and fix.
Did you try this?
ptr = const_cast<int *>(ptr_to_a);
That should help it compile but it's not really by accident due to the cast.
In C++, Using Microsoft Visual Studio-2008
const int a = 3; /* I promisse i won't change a */
int * ptr1 = const_cast<int*> (&a);
*ptr1 = 5; /* I'm a liar, a is now 5 . It's not okay. */
cout << "a = " << a << "\n"; /* prints 3 */
int arr1[a]; /* arr1 is an array of 3 ints */
int temp = 2;
/* or, const volatile int temp = 2; */
const int b = temp + 1; /* I promisse i won't change b */
int * ptr2 = const_cast<int*> (&b);
*ptr2 = 5; /* I'm a liar, b is now 5 . It's okay. */
cout << "b = " << b << "\n"; /* prints 5 */
//int arr2[b]; /* Compilation error */
In C, a const variable can be modified through its pointer; however it is undefined behavior. A const variable can be never used as length in an array declaration.
In C++, if a const variable is initialized with a pure constant expression, then its value cannot be modified through its pointer even after try to modify, otherwise a const variable can be modified through its pointer.
A pure integral const variable can be used as length in an array declaration, if its value is greater than 0.
A pure constant expression consists of the following operands.
A numeric literal (constant ) e.g. 2, 10.53
A symbolic constant defined by #define directive
An Enumeration constant
A pure const variable i.e. a const variable which is itself initialized with a pure constant expression.
Non-const variables or volatile variables are not allowed.
Some of these answers point out that the compiler can optimize away the variable 'a' since it is declared const. If you really want to be able to change the value of a then you need to mark it as volatile
const volatile int a = 3; // I promise i won't change a
int *ptr = (int *)&a;
(*ptr) = 5; // I'm a liar, a is now 5
Of course, declaring something as const volatile should really illustrate just how silly this is.
this will create a runtime fault. Because the int is static. Unhandled exception. Access violation writing location 0x00035834.
void main(void)
{
static const int x = 5;
int *p = (int *)x;
*p = 99; //here it will trigger the fault at run time
}
You probably want to use const_cast:
int *ptr = const_cast<int*>(ptr_to_a);
I'm not 100% certain this will work though, I'm a bit rusty at C/C++ :-)
Some readup for const_cast: http://msdn.microsoft.com/en-us/library/bz6at95h(VS.80).aspx
const int foo = 42;
const int *pfoo = &foo;
const void *t = pfoo;
void *s = &t; // pointer to pointer to int
int **z = (int **)s; // pointer to int
**z = 0;
The article you were looking at might have been talking about the difference between
const int *pciCantChangeTarget;
const int ci = 37;
pciCantChangeTarget = &ci; // works fine
*pciCantChangeTarget = 3; // compile error
and
int nFirst = 1;
int const *cpiCantChangePointerValue = &nFirst;
int nSecond = 968;
*pciCantChangePointerValue = 402; // works
cpiCantChangePointerValue = &ci; // compile error
Or so I recall-- I don't have anything but Java tools here, so can't test :)
#include<iostream>
int main( void )
{
int i = 3;
const int *pi = &i;
int *pj = (int*)&i;
*pj = 4;
getchar();
return 0;
}
I was looking on how to convert between consts and I found this one http://www.possibility.com/Cpp/const.html maybe it can be useful to someone. :)
I have tested the code below and it successfully changes the constant member variables.
#include <iostream>
class A
{
private:
int * pc1; // These must stay on the top of the constant member variables.
int * pc2; // Because, they must be initialized first
int * pc3; // in the constructor initialization list.
public:
A() : c1(0), c2(0), c3(0), v1(0), v2(0), v3(0) {}
A(const A & other)
: pc1 (const_cast<int*>(&other.c1)),
pc2 (const_cast<int*>(&other.c2)),
pc3 (const_cast<int*>(&other.c3)),
c1 (*pc1),
c2 (*pc2),
c3 (*pc3),
v1 (other.v1),
v2 (other.v2),
v3 (other.v3)
{
}
A(int c11, int c22, int c33, int v11, int v22, int v33) : c1(c11), c2(c22), c3(c33), v1(v11), v2(v22), v3(v33)
{
}
const A & operator=(const A & Rhs)
{
pc1 = const_cast<int*>(&c1);
pc2 = const_cast<int*>(&c2),
pc3 = const_cast<int*>(&c3),
*pc1 = *const_cast<int*>(&Rhs.c1);
*pc2 = *const_cast<int*>(&Rhs.c2);
*pc3 = *const_cast<int*>(&Rhs.c3);
v1 = Rhs.v1;
v2 = Rhs.v2;
v3 = Rhs.v3;
return *this;
}
const int c1;
const int c2;
const int c3;
int v1;
int v2;
int v3;
};
std::wostream & operator<<(std::wostream & os, const A & a)
{
os << a.c1 << '\t' << a.c2 << '\t' << a.c3 << '\t' << a.v1 << '\t' << a.v2 << '\t' << a.v3 << std::endl;
return os;
}
int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
A ObjA(10, 20, 30, 11, 22, 33);
A ObjB(40, 50, 60, 44, 55, 66);
A ObjC(70, 80, 90, 77, 88, 99);
A ObjD(ObjA);
ObjB = ObjC;
std::wcout << ObjA << ObjB << ObjC << ObjD;
system("pause");
return 0;
}
The console output is:
10 20 30 11 22 33
70 80 90 77 88 99
70 80 90 77 88 99
10 20 30 11 22 33
Press any key to continue . . .
Here, the handicap is, you have to define as many pointers as number of constant member variables you have.
we can change the const variable value by the following code :
const int x=5;
printf("\nValue of x=%d",x);
*(int *)&x=7;
printf("\nNew value of x=%d",x);
#include<stdio.h>
#include<stdlib.h>
int main(void) {
const int a = 1; //a is constant
fprintf(stdout,"%d\n",a);//prints 1
int* a_ptr = &a;
*a_ptr = 4;//memory leak in c(value of a changed)
fprintf(stdout,"%d",a);//prints 4
return 0;
}
Final Solution: it will change const variable a value;
cont int a = 10;
*(int*)&a= 5; // now a prints 5
// works fine.
The step you're missing is that you don't need the int* pointer. The line:
const int *ptr_to_a = &a; // I still promiss i won't change a;
actually says you won't change ptr_to_a, not a. So if you changed your code to read like this:
const int a = 3; // I promise I won't change a
const int *ptr_to_a = &a; // I promise I won't change ptr_to_a, not a.
(*ptr_to_a) = 5; // a is now 5
a is now 5. You can change a through ptr_to_a without any warning.
EDIT:
The above is incorrect. It turns out I was confusing a similar trick with a shared_ptr, in which you can get access to the raw pointer and modify the internal data value without firing off any warnings. That is:
#include <iostream>
#include <boost/shared_ptr.hpp>
int main()
{
const boost::shared_ptr<int>* a = new boost::shared_ptr<int>(new int(3));
*(a->get()) = 5;
std::cout << "A is: " << *(a->get()) << std::endl;
return 0;
}
Will produce 5.