-2
#include <iostream>

using namespace std;

class MyClass {
    int x;
  public:
    MyClass (int val) : x(val) {
        cout << "constructed :" << this << endl;
    }
    int& get() {
        cout << "x is : " << x << endl ;
        return x;
    }
};

int main () {
    MyClass foo = {10};
    foo.get() = 20;
    foo.get();
    foo = 30;
    cout << &foo << endl;
    foo.get();
}

I get the following output:

constructed :0x7fffc44ef920
x is : 10
x is : 20
constructed :0x7fffc44ef924
0x7fffc44ef920
x is : 30

Why is this foo.get() = 20 a legitimate way of changing the value of 'x' in the object foo?

Also why is this foo = 30 constructing a new object at the address 0x7fffc44ef924 ? What is this object type?

Also why does this: cout << &foo << endl; print the address of the original MyClass foo object instantiated at the beginning of the main function (at address 0x7fffc44ef920)?

How do you reference the 'new' foo at the address 0x7fffc44ef924?

2 Answers2

1

Why is this foo.get() = 20 a legitimate way of changing the value of 'x' in the object foo?

Because you're returning a reference to x and that's how references behave. In fact, the only reason I know of to return a reference from a function (int &get()) is to allow this behaviour. You might do this, for example, if you were implementing operator[].

Sometimes you want to return a const reference (const int &foo()) in order to avoid a copying the value, but you'd only do that with a class or struct.

Also why is this foo = 30 constructing a new object at the address 0x7fffc44ef924 ? What is this object type?

Because MyClass has a constructor that takes one int argument, the compiler interprets this as a way to convert an int to a MyClass, which is what is happening here. It's equivalent to foo = MyCLass(int) If you don't want this behaviour, you can declare MyClass(int) as explicit:

explicit MyClass( int val ) {...

Also why is this foo = 30 constructing a new object at the address 0x7fffc44ef924 ? What is this object type?

Also why does this: cout << &foo << endl; print the address of the original MyClass foo object instantiated at the beginning of the main function (at address 0x7fffc44ef920)?

First, the implicit MyClass(30) I described above is used to construct a new MyClass object. The address of this object happens to have the address 0x7fffc44ef924 then the new object is copied into the old object, at 0x7fffc44ef920. Probably if you had optimization turned on you would only see one address, since the compiler would see that creating a whole new object and then copying it is a wast of CPU cycles.

How do you reference the 'new' foo at the address 0x7fffc44ef924?

You can't, that object was created and destroyed in one line of code. Once it was copied over the original object like I described above, it was deleted.

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
0

Change your constructor to an explicit one, by adding the explicit keyword before your constructor, like this:

explicit  MyClass (int val) : x(val) {
  cout << "constructed :" << this << endl;
}

Then, you will get very informative messages from the compiler:

prog.cc: In function 'int main()':
prog.cc:18:22: error: converting to 'MyClass' from initializer list would use explicit constructor 'MyClass::MyClass(int)'
     MyClass foo = {10};
                      ^
prog.cc:21:11: error: no match for 'operator=' (operand types are 'MyClass' and 'int')
     foo = 30;
           ^~
prog.cc:5:7: note: candidate: 'constexpr MyClass& MyClass::operator=(const MyClass&)'
 class MyClass {
       ^~~~~~~
prog.cc:5:7: note:   no known conversion for argument 1 from 'int' to 'const MyClass&'
prog.cc:5:7: note: candidate: 'constexpr MyClass& MyClass::operator=(MyClass&&)'
prog.cc:5:7: note:   no known conversion for argument 1 from 'int' to 'MyClass&&'

Read them and understand it. If they don't make sense, then you really need to study C++ more, e.g. a book.

gsamaras
  • 71,951
  • 46
  • 188
  • 305