initial value of reference to non-const must be an lvalue

A

asm23

Hi,I need some help to clarify the warning "initial value of reference
to non-const must be an lvalue".

I'm searching in this groups to find someone has the same situation like
me. I found in the Post:

//*********************************************************************
// CODE
//*********************************************************************
#include <iostream.h>

class complex {
double re, im; //Private members of class
public:
complex() { re=0.0; im=0.0; } //Empty Constructor
complex(double r, double i=0.0) //Constructor from 2 doubles
{ re=r; im=i; }
friend ostream& operator<<(ostream&, complex&);
friend inline complex operator+(complex, complex);

};

inline complex operator+(complex a1, complex a2) //Add 2 complex numbers
{ return complex(a1.re+a2.re, a1.im+a2.im); }
ostream& operator<<(ostream& os, complex& cnum) //Output a complex number
{ os << "(" << cnum.re << "," << cnum.im << ") "; return os; };

int main(void)
{ complex a(1,2), b(3,4); //Define complex numbers

cout <<"a=" << a <<",b=" << b <<" a+b = " << a+b << endl; //Print sum

}

I also get the same warning in my compiler.
but I add some statement like:

//*********************************************************************
// CODE
//*********************************************************************

int a1=2;
int b1=3;
cout<<a1+b1;

this goes very well.

What's the difference between these two code? How can I get rid of these
warnings?

Thanks

P

Pete Becker

cout <<"a=" << a <<",b=" << b <<" a+b = " << a+b << endl; //Print sum

Get rid of the noise:
cout << a+b;

Now if you get the same warning, you know where to look.

A

asm23

Pete said:
Get rid of the noise:
Thanks, you say I should use the "#pragma warning (disable:XXX) to get
rid of the warnings?

P

Pete Becker

Thanks, you say I should use the "#pragma warning (disable:XXX) to get
rid of the warnings?

No. Simplify the statement where the warning occurs.

A

asm23

Pete said:
No. Simplify the statement where the warning occurs.
I still get the warning when I change the code to: cout<<a+b;

I have another code to show, that sometimes, the type of warning became
error.

//////////////////////////////code/////////////////////////////////

int f(){
return 1;
}

int &bf=f();

error: initial value of reference to non-const must be an lvalue
////////////////////////////////////////////////////////////////////

I know the error that the return from f() is not lvalue. So, we can't
initialize the "bf".

J

Jim Langston

asm23 said:
Hi,I need some help to clarify the warning "initial value of reference
to non-const must be an lvalue".

I'm searching in this groups to find someone has the same situation
like me. I found in the Post:

//*********************************************************************
// CODE
//*********************************************************************
#include <iostream.h>

class complex {
double re, im; //Private members of class
public:
complex() { re=0.0; im=0.0; } //Empty Constructor
complex(double r, double i=0.0) //Constructor from 2
doubles { re=r; im=i; }
friend ostream& operator<<(ostream&, complex&);
friend inline complex operator+(complex, complex);

};

inline complex operator+(complex a1, complex a2) //Add 2 complex
numbers { return complex(a1.re+a2.re, a1.im+a2.im); }
ostream& operator<<(ostream& os, complex& cnum) //Output a complex

operator<< is accepting a non constant ostream& and a non constant complex&
number { os << "(" << cnum.re << "," << cnum.im << ") "; return os;
};
int main(void)
{ complex a(1,2), b(3,4); //Define complex numbers

cout <<"a=" << a <<",b=" << b <<" a+b = " << a+b << endl; //Print

You are attempting to pass to operator<< a non constant ostream& and a non
constant *temporary* complex& The temporary is the problem. Any changes
the function made to the temporary would be lost. A very simple fix. Change

ostream& operator<<(ostream& os, const complex& cnum)

And your problem should go away.

You need to learn const correctness. A temporary rvalue can be passes as a
const. I'm not sure of all the limitations, but it seems this is one of
them. Your clue that this is a const correctness error is given in the
error itself:
"initial value of reference to ***non-const*** must be an lvalue".

S

Sachin

operator<< is accepting a non constant ostream& and a non constant complex&

You are attempting to pass to operator<< a non constant ostream& and a non
constant *temporary* complex&  The temporary is the problem.  Any changes
the function made to the temporary would be lost.  A very simple fix. Change

ostream& operator<<(ostream& os, const complex& cnum)

And your problem should go away.

You need to learn const correctness.  A temporary rvalue can be passes as a
const.  I'm not sure of all the limitations, but it seems this is one of
them.  Your clue that this is a const correctness error is given in the
error itself:
"initial value of reference to ***non-const*** must be an lvalue".

--
Jim Langston
(e-mail address removed)- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -

I am not getting any warning message with above code, using Visual
Studio 6.0 Compiler, You can create temporary object to hold result of
a+b, than pass temporary object to operator<<.

c= a+b;
cout<<c;

Regards,
Sachin

A

asm23

Jim said:
operator<< is accepting a non constant ostream& and a non constant complex&

You are attempting to pass to operator<< a non constant ostream& and a non
constant *temporary* complex& The temporary is the problem. Any changes
the function made to the temporary would be lost. A very simple fix. Change

ostream& operator<<(ostream& os, const complex& cnum)

And your problem should go away.
Thanks, I fix the problems by adding "const". The sentence "A temporary
rvalue can be passes as a const" is very important and I will remember
this. Also, I should learn some stuff on "const" more carefully.

A

asm23

Sachin said:
I am not getting any warning message with above code, using Visual
Studio 6.0 Compiler, You can create temporary object to hold result of
a+b, than pass temporary object to operator<<.

c= a+b;
cout<<c;

Regards,
Sachin

Thanks, I'm using vc6, but I'm using the compiler supplied by Intel. So,
they have some differences. When I use the original compiler in VC6,
there's no warning even I set the warning level to 4, which is the
highest level.

T

Thanks, I'm using vc6, but I'm using the compiler supplied by Intel. So,
they have some differences. When I use the original compiler in VC6,
there's no warning even I set the warning level to 4, which is the
highest level.- Hide quoted text -

To Sachin, c isn't a temporary object, you're confusing the issue.
To asm23, no surprise about VC6 and warning level 4 - read past
posts in this n.g and you'll soon be chucking VC6 in the bin.

R

Ron Natalie

asm23 said:
Hi,I need some help to clarify the warning "initial value of reference
to non-const must be an lvalue".

I'm searching in this groups to find someone has the same situation like
me. I found in the Post:

//*********************************************************************
// CODE
//*********************************************************************
#include <iostream.h>

Most likely spurious
class complex {

Since you're using some nonstandard compiler (as a result of iostream.h)
I'd be real careful about using type names that are defined in the

P

Pete Becker

I still get the warning when I change the code to: cout<<a+b;

Now that you've isolated the problem, think about what that statement does.

A

asm23

Ron said:
Most likely spurious

Since you're using some nonstandard compiler (as a result of iostream.h)
I'd be real careful about using type names that are defined in the
Thanks for your reply. And Thanks for pointing out some mistakes in my code.
Now, I have change the whole code to standard type, which I use
namespaces. ALL works very well And NO "initial value ....." warnings
any more.

//------------------------CODE----------------------------------
#include <iostream>
using namespace std;

class complex {
double re, im; //Private members of class
public:
complex() { re=0.0; im=0.0; } //Empty Constructor
complex(double r, double i=0.0) //Constructor from 2 doubles
{ re=r; im=i; }
friend ostream& operator<<(ostream&, complex&);
friend inline complex operator+(complex, complex);
};

inline complex operator+(complex a1, complex a2) //Add 2 complex numbers
{
return complex(a1.re+a2.re, a1.im+a2.im);
}

ostream& operator<<(ostream& os, complex & cnum) //Output a complex
number
{
os << "(" << cnum.re << "," << cnum.im << ") "; return os;
}

int main(void)
{
complex a(1,2), b(3,4); //Define complex numbers

complex c=a+b;
cout << c << endl; //Print sum

int a1=2;
int b1=3;
cout<<a1+b1 <<endl;

return 0;
}
//----------------------------------------------------------------

A

asm23

Ron said:
Most likely spurious

Since you're using some nonstandard compiler (as a result of iostream.h)
I'd be real careful about using type names that are defined in the
Thanks for your reply. And Thanks for pointing out some mistakes in my code.
Now, I have change the whole code to standard type, which I use
namespaces. ALL works very well And NO "initial value ....." warnings
any more.

//------------------------CODE----------------------------------
#include <iostream>
using namespace std;

class complex {
double re, im; //Private members of class
public:
complex() { re=0.0; im=0.0; } //Empty Constructor
complex(double r, double i=0.0) //Constructor from 2 doubles
{ re=r; im=i; }
friend ostream& operator<<(ostream&, complex&);
friend inline complex operator+(complex, complex);
};

inline complex operator+(complex a1, complex a2) //Add 2 complex numbers
{
return complex(a1.re+a2.re, a1.im+a2.im);
}

ostream& operator<<(ostream& os, complex & cnum) //Output a complex
number
{
os << "(" << cnum.re << "," << cnum.im << ") "; return os;
}

int main(void)
{
complex a(1,2), b(3,4); //Define complex numbers

complex c=a+b;
cout << c << endl; //Print sum

int a1=2;
int b1=3;
cout<<a1+b1 <<endl;

return 0;
}
//----------------------------------------------------------------

J

Jim Langston

asm23 wrote:
[SNIP]
Thanks for your reply. And Thanks for pointing out some mistakes in
my code. Now, I have change the whole code to standard type, which I
use namespaces. ALL works very well And NO "initial value ....." warnings
any more.

#include <iostream>
using namespace std;

This is generally frowned up except for the most trivial of programs. It is
a quick way to not have to worry about namespaces, but once you start
getting more complicated programs it can cause problems. using namespace
std; brings everything in std into the unnamed namespace. For trivial
programs this is usually not an issue, but sooner or later you're going to
wind up using some code you download somewhere where someing in their code
decided to make a structure called string, which will now conflict with
std::string. or list. or vector. or map...

My solution: never use "using..." at all. I always preeceed the namespace
whre used. I.E. I would code the line as:
friend std:stream& operator<<( std:stream&, complex& );

Another good solution: only bring into the unnamed namespace the things you
need from std.
using std:stream;

"using namespace std;" is not wrong, per se, it's just generally not
considered the best practice. And it should never be used in a header.
class complex {
double re, im; //Private members of class

Okay, you have a commant stating that these are private members. So you're
using 27+ characters to comment something out that you might as well
document much better by preceeding htis line with:
private:

I.E.

class complex {
private:
double re, im;

Yes, it is not needed. But it documents your code with code and you no
longer need the comment.
public:
complex() { re=0.0; im=0.0; } //Empty Constructor

Sooner or later you are going to have to learn about initialization lists,
and sooner is probably better than later. Some things can only be
initialized in initialization lists (base classes, references, etc...)
Using an initilaization list the above would become:

complex(): re(0.0), im(0.0) {};

It takes a little getting used to and at first looks weird as heck, but
after you finally get used to it it becomes natural. It's also a bit more
effecient although for trivial types such as double you won't notice a
difference, for some large class with heavy constructors and assignment
operators you probabably would.
complex(double r, double i=0.0) //Constructor from 2 doubles
{ re=r; im=i; }

Same comment about the initializastion list. However. You have 2
constructors that you can use by three differet ways: I.E.
complex();
complex( 1.0 );
complex ( 1.0, 2.0 );

but why use 2 when you can accomplish the same thing in one constructor?

complex( double r = 0.0, double i = 0.0 ): re(r), im(i) {}

which will support no paramters, one parameter or two parameters and do the
exact same thing as your two constructors.
friend ostream& operator<<(ostream&, complex&);
friend inline complex operator+(complex, complex);
};

inline complex operator+(complex a1, complex a2) //Add 2 complex
numbers {
return complex(a1.re+a2.re, a1.im+a2.im);
}

ostream& operator<<(ostream& os, complex & cnum) //Output a complex
number
{
os << "(" << cnum.re << "," << cnum.im << ") "; return os;
}

int main(void)

In C++ this would be written as
int main()

void is generally not used in C++ to indicate no parameters, an empty
parameter list is. Again, it's not wrong to use void, just not considered
the best practice.

J

James Kanze

asm23 wrote:
[SNIP]
class complex {
double re, im; //Private members of class
Okay, you have a commant stating that these are private
members. So you're using 27+ characters to comment something
out that you might as well document much better by preceeding
htis line with: private:

class complex {
private:
double re, im;
Yes, it is not needed. But it documents your code with code
and you no longer need the comment.

Normally, it's not needed even as a comment. Most places will
have standards specifying the order of declarations---if the
order has the private members first, then you expect everything
until you encounter an access specifier to be private,
regardless.

Also, of course, you always expect data members to be private.

Following the normal, expected practice, doesn't require a
comment, even if the comment is in the form of compilable (but
unnecessary) code.

If the local standards specify public before private, and you
pointing out that it is private, but stating why you've placed
it in an unexpected location.

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.