munish
munish

Reputation: 4634

Error : non-lvalue in assignment

#include <iostream>
using namespace std;

class Array
{
   friend ostream &operator<<( ostream &, const Array & );
public:
   Array( int = 5 ); 
   Array( const Array & ); 
   ~Array(); 
   int getSize() const; 
   const Array &operator=( const Array & );
   // subscript operator for non-const objects returns modifiable lvalue
   int &operator[]( int );              
   // subscript operator for const objects returns rvalue
   int operator[]( int ) const;  
private:
   int size; 
   int *ptr; 
}; 

Array::Array( int arraySize )
{
   size = ( arraySize > 0 ? arraySize : 5 ); // validate arraySize
   ptr = new int[ size ]; 

   for ( int i = 0; i < size; i++ )
      ptr[ i ] = 0; 
}

// must receive a reference to prevent infinite recursion
Array::Array( const Array &arrayToCopy ) 
   : size( arrayToCopy.size )
{
   ptr = new int[ size ]; // create space for pointer-based array

   for ( int i = 0; i < size; i++ )
      ptr[ i ] = arrayToCopy.ptr[ i ]; // copy into object
} 

Array::~Array()
{
   delete [] ptr; // release pointer-based array space
} 

int Array::getSize() const
{
   return size; // number of elements in Array
} 

const Array &Array::operator=( const Array &right )
{
   if ( &right != this ) // avoid self-assignment
   {
      if ( size != right.size )
      {
         delete [] ptr; // release space
         size = right.size; // resize this object
         ptr = new int[ size ]; // create space for array copy
      }

      for ( int i = 0; i < size; i++ )
         ptr[ i ] = right.ptr[ i ]; // copy array into object
   }

   return *this; 
}

// overloaded subscript operator for non-const Arrays reference return creates a modifiable lvalue
int &Array::operator[]( int subscript )
{
cout << " ***************Inside non-sonstant operator[] function: Lvalue test*********** ";
   if ( subscript < 0 || subscript >= size )
   {
      cerr << "\nError: Subscript " << subscript 
         << " out of range" << endl;
      exit( 1 ); // terminate program; subscript out of range
   }

   return ptr[ subscript ]; // reference return
}

// overloaded subscript operator for const Arrays const reference return creates an rvalue
int Array::operator[]( int subscript ) const
{
cout << " ***************Inside sonstant operator[] function: Rvalue test*********** ";
   if ( subscript < 0 || subscript >= size )
   {
      cerr << "\nError: Subscript " << subscript 
         << " out of range" << endl;
      exit( 1 ); 
   } 

   return ptr[ subscript ]; // returns copy of this element
}


// overloaded output operator for class Array 
ostream &operator<<( ostream &output, const Array &a )
{
   int i;
   // output private ptr-based array 
   for ( i = 0; i < a.size; i++ )
   {
      output << a.ptr[ i ] << " ";

      if ( ( i + 1 ) % 4 == 0 )
         output << endl;
   } // end for

   if ( i % 4 != 0 ) 
      output << endl;

   return output; 
} 

int main()
{
   Array integers1( 4 ); 
   Array integers2; // 5-element Array by default
   const Array& integers4=integers1;
    //integers4[3] = 2000; //Error : non-lvalue in assignment 
    integers1 = integers1;  //valid
    integers4 = integers1;  //Error : binary '=' : no operator found 
    //which takes a left-hand operand of type 'const Array' (or there is no 
    //acceptable conversion)
    cout << "\nintegers1[3] is " << integers4[ 3 ];

   return 0;
} 

Gives errors :

1) In function `int main()':

'=' : left operand must be l-value

2) binary '=' : no operator found which takes a left-hand operand of type 'const Array' (or there is no acceptable conversion)

Please help.

Upvotes: 2

Views: 7586

Answers (3)

On the particular pieces of code:

Array integers1( 4 ); 
const Array& integers4=integers1;
//integers4[3] = 2000; //Error : non-lvalue in assignment 

You are using a constant reference to an array to call a member function, and the compiler will resolve the call to int Array::operator[]( int x ) const (the other version of operator[] requires a non-const object). The expression yields an rvalue and you cannot assign to it.

integers4 = integers1;  //Error : binary '=' : no operator found 

Again the issue is that integers4 is a constant lvalue, and that means that it cannot be modified (because of the const in there).

Upvotes: 1

user258808
user258808

Reputation: 734

You cannot modify a const reference, Try this:

//Snippet1
Array& integers4=integers1;
integers4[3] = 2000; 

To clarify OP's doubt about modifying const references:

//Snippet2
//This will not compile as you saw.
const Array& integers4=integers1;
integers4[3] = 2000; //errors

Now this is what Xeo did in his reply to this post. He did not change the reference, but instead the original variable.

//Snippet2
//This will compile and work identically to Snippet1.
const Array& integers4=integers1;
interger1[3] = 2000; 

Upvotes: 3

shoosh
shoosh

Reputation: 78914

First error - integers4 is a const Array so you can only use the const operator[] which returns int rather than int&. you cannot assign to a returned temporary int, nor should you be able to change something that is a const.
The second error is probably a derivative of the first.

Upvotes: 2

Related Questions