Temporary Objects and pass by (const/non-const) `value`

319 views Asked by At

Life time of temporary objects last until the full length of the expression in which it was created when used without references.

Consider the following:

 class My
 {
   int i;
   public:
     void increment()
     {
       i++;
     }
 };

 My withOutConst()
 {
   return My();
 }

 const My withConst()
 {
   return My();
 }

 int main()
 {
   My ob;
   withOutConst().increment();  // Case 1
   withConst().increment();     // Case 2

   return 0;
 }

As I understand the compiler creates a temporary object( of type const My) to hold the return value in the above cases. And, I am trying to modify the temporary object.

(1) Compiles fine and

(2) Results in a compile time error with the error:

error: passing 'const My' as 'this' argument of void My::increment() discards qualifiers

That means basically this is of type My and not const My as it is called for a non-const function.

My question:

I am trying to modify a temporary object of type const My by calling a non-const member function.

Then why don't I get the same error in case(1) because I am operating over an object of the type const My in both the cases.

I understand that this is related to the return type of the functions but am unable to fully comprehend because at the end it boils down to the function(void My::increment()) which is trying to modify temporaries of type const My in both the cases.

5

There are 5 answers

5
David Rodríguez - dribeas On BEST ANSWER

A temporary has a type, that type can be const, and it can be non-const. You can call a non-const member function only on a non-const object. withOutConst() yield a temporary of type My, withConst() yields a temporary of type const My.

Maybe you have the misconception that a temporary is always const? If that is the case, then it is wrong.

0
Chad On

Then why don't I get the same error in case(1) because I am operating over an object of the type const My in both the cases.

That simply isn't true.

 My withOutConst()
 {
   return My();
 }

 const My withConst()
 {
   return My();
 }

withOutConst returns an object of type My, while withConst() returns an object of type const My. Even though in both cases you are using them as temporaries, their underlying type My and const My are exactly as coded in the function signatures.

0
Neil Kirk On
  1. Returns a temporary non-const object, calls the function on it, then it goes out of scope.
  2. Returns a temporary const object, which does not allow non-const function to be called.

A temporary object does not have to be const.

0
Mike Seymour On

As I understand the compiler creates a temporary object( of type const My) to hold the return value in the above cases.

No. The return value of withOutConst() is not const, since you didn't declare it const. The observed behaviour follows from that.

You may be confusing being const with being an rvalue. In many situations, an rvalue can't be modified; but you can call a nonconstant member function on one.

0
user2623609 On

If this is a simplified version of something you're trying to do in a more complex code base, where you still want to use some some sort of counter on a const object, then you need to mark your "i" variable as "mutable". Like so:

class My
{
   mutable int i;
public:
   void increment()
   {
      i++;
   }
};