I heard references in c++ can be intitalized only once but this is giving me 1 is my output and not returning any error!
struct f {
f(int& g) : h(g) {
h = 1;
}
~f() {
h = 2;
}
int& h;
};
int i() {
int j = 3;
f k(j);
return j;
}
The destructor of f is called after the return value j is captured.
You might want something like this, if you wanted j to be 2:
int i( )
{
int j=3;
{
f k(j);
}
return j;
}
See C++ destructor & function call order for a more detailed description of the order of destruction and the return statement.
You are still initializing the reference only once; assignment and initialization are not the same. The initialization sets up h so that it references j (which you never change). Your assignment merely changes the value of j which is the same as h, but does not cause h to refer to a different variable.
I hope this code is only to display the issue, storing a reference to a variable defined outside of the class is very dangerous as your class doesn't have any control over (or knowlege of) when the referenced variable goes out of scope.
Related
As the example below, I define 2 variables x and y. When I call the lambda function twice, it seems like it will not destroy the copy. From 11.14 — Lambda captures | Learn C++ - Learn C++, it says:
Because captured variables are members of the lambda object, their values are persisted across multiple calls to the lambda!
How does C++ manage the memory for lambda function?
int main() {
int x = 1;
static int y = 1;
auto fun = [=]() mutable{
x++;
y++;
cout<<"Inside:\t\t";
cout<<"x:"<<x<<"\t"<<"y:"<<y<<endl;
};
for (int i = 0; i<2; i++) {
fun();
cout<<"Outside:\t";
cout<<"x:"<<x<<"\t"<<"y:"<<y<<endl<<endl;
}
}
Output:
Inside: x:2 y:2
Outside: x:1 y:2
Inside: x:3 y:3
Outside: x:1 y:3
It stores it inside the object itself. Another way to think of your lambda is below. This is "kind of" equivalent to what the compiler is generating, and yes, I'm changing scopes around a bit and I know that, but this may be clearer to a beginner at C++.
static int y = 1; // Moved this out from main
class my_lambda{
public:
my_lambda(int x) : _x(x) {}
~my_lambda() = default;
void operator()()
{
_x++;
y++;
cout<<"Inside:\t\t";
cout<<"_x:"<<_x<<"\t"<<"y:"<<y<<endl;
}
private:
int _x;
};
int main() {
int x = 1;
my_lambda fun{x}; // "Captures" x
for (int i = 0; i<2; i++) {
fun();
cout<<"Outside:\t";
cout<<"x:"<<x<<"\t"<<"y:"<<y<<endl<<endl;
}
}
As you can hopefully see, the "fake lambda" class I made is doing the same thing your actual lambda is. It "captures" x as part of its constructor and copies it to internal storage, which I called _x. And y is just in scope for it, though I moved to global to be above the class declaration.
I'm overloading the () operator to make a class that's callable, which is a normal thing to do in some circumstances. See operator overloading if you wish for more information.
So this is "kind of, sorta" how lambdas work. They take your body and put it into the operator() of the object that's generated, and anything captured is one of the object's variables, with either the actual object (if by value) or a reference, if captured that way.
And to directly answer your question: when fun goes out of scope, it is freed, both in a lambda, and my case.
I understand the concept of references in C++, and I understand what they do when used in function parameters, but I am still very much confused on how they work with return types.
For example, when used in parameters, this code:
int main (void) {
int foo = 42;
doit(foo);
}
void doit (int& value) {
value = 24;
}
is similar to this code:
int main (void) {
int foo = 42;
doit(&foo);
}
void doit (int* value) {
*value = 24;
}
(knowing that the compiler will automatically put an asterisk in front of value every time it is used in the first code sample of doit, but in the latter you'd have to put the asterisk in yourself every time you try to use value)
So when used as a reference what does this next code (using reference in a return type) translate to? Does it return a pointer to an int? Or would it just return an int?
int main (void) {
int* foo = /*insert useful place in memory*/;
foo = doit(foo);
}
int& doit (int* value) {
//insert useful code
}
It means you return by reference, which is, at least in this case, probably not desired. It basically means the returned value is an alias to whatever you returned from the function. Unless it's a persistent object it's illegal.
For example:
int& foo () {
static int x = 0;
return x;
}
//...
int main()
{
foo() = 2;
cout << foo();
}
would be legal and print out 2, because foo() = 2 modifies the actual value returned by foo.
However:
int& doit () {
int x = 0;
return x;
}
would be illegal (well, accessing the returned value would), because x is destroyed when the method exits, so you'd be left with a dangling reference.
Returning by reference isn't common for free functions, but it is for methods returning members. For example, in the std, the operator [] for common containers return by reference. For example, accessing a vector's elements with [i] returns an actual reference to that element, so v[i] = x actually changes that element.
Also, I hope that "is essentially equal to this code" means that they're semantically sort of (but not really) similar. Nothing more.
It means that you return a pointer to the memory address where the correspondent data is, instead of the very data.
Assuming this code (to make it comparable to the first example) :
int main (void) {
int* foo = /*insert useful place in memory*/;
*foo = doit(foo);
}
int& doit (int* value) {
*value = 24;
return *value;
}
The int& is not really useful as a return type in this case, because it provides access to the variable in memory (of which you pass the pointer to the function).
Does it return a pointer to an int? Or would it just return an int?
No, it returns a reference to an int. If you want, you can look at it as a pointer which can not be nullptr.
Hmm, the best way to know the answer is to have a try...
Your codes will not pass type check, because doit will return a reference of int while you accept the return value as a pointer of int.
You can have a look at this:
#include<iostream>
using namespace std;
int& doit (int* value) {
value[0] = 3;
return value[4];
}
int main (void) {
int* foo = new int[10];
for (int i=0; i<10; i++)
foo[i] = i;
int& bar = doit(foo);
cout<<bar<<endl;
for (int i=0; i<10; i++)
cout<<foo[i]<<" ";
cout<<endl;
bar = 12;
for (int i=0; i<10; i++)
cout<<foo[i]<<" ";
cout<<endl;
return 0;
}
The variable "bar" will accept the return value, and it can be used change the content of "foo". As is mentioned by Luchian, it maybe dangerous to return a reference from the function, because the later codes might modify a value which is in the stack.
Let's say in a class a constructor is overloaded. Can multiple data members be initialized for the single object using different constructors of the same class?
eg :
class demo{
int size;
double k;
public:
demo(int s){
size=s;
}
demo(double p){
k = size+p;
}
void show(){
cout<<size<<" "<<k<<"\n";
}
};
int main(){
demo a = demo(0);
a = 4.7;
a.show();
return 0;
}
Is this possible?
No, once the object is constructed, it's constructed.
Let's go through your code and see what it does (assuming no optimizations, please note that many modern compilers will do some copy-elision even in debug or -O0 modes):
demo(0);
The code demo(0) calls the demo(int s) constructor. A temporary rvalue is created. So now we have a temporary object with the values:
size = 0
k = uninitialized
demo a = demo(0);
demo a is then created using an implicit copy constructor.
We now have a demo object named a with the following values:
size = 0
k = uninitialized
a = 4.7;
Because a is already constructed, this will call an implicit assignment-operator. The default assignment-operator will copy all the values from one object into the other object. This means the 4.7 needs to be converted into a demo object first. This is possible because of your demo(double p) constructor.
So a temporary demo object will be created with the values:
size = uninitialized
k = uninitialized + 4.7 = undefined
These values will be copied into a and so both of a's data members will be undefined.
Possible Solutions
songyuanyao's solution of using a constructor with multiple parameters is one good way of doing it.
Using setters is another way.
Either way, I would recommend having your constructors provide default values for your data-members.
demo(int s)
{
size = s;
k = 0.0; // or some other suitable value
}
Here's how you could create a setter.
void setK (double p)
{
k = size + p;
}
You could then do this:
int main ()
{
demo a (0) ;
a.setK (4.7) ;
a.show () ;
return 0 ;
}
I think you're after the Builder Pattern.
You should define a ctor which can take multiple parameters to initialize multiple data members:
demo(int s, double p) {
size = s;
k = size + p;
}
and then
int main() {
demo a(0, 4.7);
a.show();
return 0;
}
I'm learning how to use C++ lambda functions along with <functional>'s function class. I am trying to solve this Code Golf as practice (challenge is Curry for Dinner)
I have this function:
// This creates a function that runs y a number of
// times equal to x's return value.
function<void()> Curry(function<int()> x, function<void()> y)
{
return [&]() {
for (int i = 0; i < x(); i++)
{
y();
}
};
}
To test this I have this code in my main():
auto x = [](){ return 8; };
auto y = [](){ cout << "test "; };
auto g = Curry(x, y);
This throws Access violation reading location 0xCCCCCCCC. in Functional.h.
Yet when I copy-paste the lambda function from inside Curry() to inside my main like this:
auto x = [](){ return 8; };
auto y = [](){ cout << "test "; };
auto g = [&]() {
for (int i = 0; i < x(); i++)
{
y();
}
};
I get the code running as expected. Why does this happen?
You have a few problems.
Here:
return [&]() {
you capture by reference. Any variables you capture has to have a lifetime that exceeds your own. It means that running the lambda becomes undefined behavior after the variables you capture&use lifetime ends. As you are returning this lambda, and capturing local state, this seems likely to happen. (Note I said variables -- due to a quirk in the standard, [&] captures variables not the data referred to by variables, so even capturing & function arguments by [&] is not safe. This may change in future revisions of the standard... There are neat optimizations that this particular set of rules allow in lambda implementations (reduce [&] lambdas to having 1 pointer worth of state(!)), but it also introduces the only case in C++ where you have a reference to a reference variable in effect...)
Change it to
return [=]() {
and capture by-value.
Or even:
return [x,y]() {
to list your captures explicitly.
When using a lambda which does not outlive the current scope, I use [&]. Otherwise, I capture by value explicitly the stuff I am going to use, as lifetime is important in that case.
Next:
for (int i = 0; i < x(); i++)
you run x once for every loop iteration. Seems silly!
Instead:
auto max = x();
for (auto i = max; i > 0; --i)
which runs max times, and as it happens works if the return value of x was changed to unsigned int or whatever.
Or:
int max = x();
for (int i = 0; i < max; ++i)
which both runs x once, and behaves better if x returns -1.
Alternatively you can use the obscure operator -->:
int count = x();
while( count --> 0 )
if you want to make your code unreadable. ;)
I want to do something like this:
int displayAll(Message *m, string &lastIndex, int &NumPrinted = 0 );
It gives me error, cribbing about int to int&.
I tried this too:
int temp =0;
int displayAll(Message *m, string &lastIndex, int &NumPrinted = temp );
Still it gives following error:
error: ISO C++ forbids in-class initialization of non-const static member 'temp'
Even static int temp; gives error.
error: ISO C++ forbids in-class initialization of non-const static member 'temp'
The problem with the first line of code you mention is that you are trying to pass a reference to a temporary variable
class Foo {
int displayAll(Message *m, bool &moreElements, string &lastIndex, int &NumPrinted = 0 );
};
The second bit of code complains because you were trying to initialize a class member statically.
class Foo {
int temp =0;
int displayAll(Message *m, bool &moreElements, string &lastIndex, int &NumPrinted = temp );
};
(I am putting your code inside of a class declaration to be clear about what is happening).
An easy way out of your problem that does not introduce a static variable is explicit function overloading:
class Foo {
inline int displayAll(Message *m, bool &moreElements, string &lastIndex) {
int dummy = 0;
return displayAll(m, moreElements, lastIndex, dummy);
}
int displayAll(Message *m, bool &moreElements, string &lastIndex, int &NumPrinted);
};
There's a bit of boilerplate, but it achieves what you want.
Hope this helps.
EDIT: Some more clarification. The core of the problem stems from the fact that the function must take a reference to some memory that it can modify. If you pass it a temporary variable (temporary as in the C++ meaning of the term, not just the english language term ) (as in your first line of code), it's illegal C++, since you usually copy a temporary to a value before you use it as an argument to a function:
void bar( int someNum = 0 ); // think of this as creating a temporary rvalue 0
// and then copying it into the function for use.
// temporary rvalues arise in expressions like
int v = 5 + 5; // the result of 5 + 5 is stored in a temporary rvalue, and then
// copied into v (which is an lvalue in this case).
So we need something that is an "lvalue", either some global variable somewhere or a temporary local variable ( in the english language sense ) as I gave in my answer. I was about to write a solution using a static variable, but there is a large flaw- since the static variable will be shared by all instances of your class, it will start out 0 and then be different every time you call the method ( since it would have been edted by the previous call). Even worse, in the case of multiple threads, you would be reading/writing to the same place of memory from several processors, so the value will be complete garbage, and you ill rape your processor cores' caches as each write will invalidate the cache of every other core. It's ugly, please don't do it. :P
By using my first solution you make the temporary variable very local, without much impact on anything else.
You can't do this for a non-const reference unless you declare temp to be static: see this stackoverflow post.
I fpund this interesting way of achieving this too:
class demo {
public:
void displayAll(int &x, int y = 0 ) {
int *p;
if(y)
p = (int*)y;
if(p) *p = 10;
x = 4;
}
};
int main() {
int x=0, y=0;
demo *obj = new demo();
obj->displayAll((x);
//obj->temp(x,(int)&y);
cout << "\n x= " << x << " y " << y;
return 0;
}