Mayank Jain
Mayank Jain

Reputation: 2564

Reference update in C++

I have a simple question regarding reference update in c++. Consider below C++ code:

class A
{
    int b;

    public:
    int& setb();
    int getb();
    A();
    A &operator= (const A &t)
    {
        cout<<"Assignment called"<<endl;
    }
    A(int i):b(i) {
        cout<<"Copy contructor called"<<endl;
    }
};

int A::getb()
{
    cout<<this->b<<endl;
}

int& A::setb()
{
    return b;
}

A::A()
{
    cout<<"constructor called"<<endl;
}

int main()
{
    A a;
    cout<<"About to set reference"<<endl;
    a.setb()=5;
    a.getb();

    return 0;
}

When I update b via reference how is the value copied? Is there any default copy constructor which is being called ?

Upvotes: 1

Views: 481

Answers (3)

kh&#244;i nguyễn
kh&#244;i nguyễn

Reputation: 628

Through your code, I see that you use the default copy constructor of C++ compiler. It will use copy constructor of each non-static member of your class. Note that the generated constructor in your case will look likes:

A(const &A other) 
:   b(other.b) 
{}

and it will be called int these cases:

A a;
...
A b = a;
...
A c(a);

In other words, the copy constructor will be called when your construct new object from other object in same class. Your constructor from int is not a copy constructor.

Second, why you set b private while everybody can modified it via your setb()? I think a better way to implement your setb() is:

void A::setb(const int& val) {
    b = val;
}

Upvotes: 0

Pratik Singhal
Pratik Singhal

Reputation: 6492

No, when you update b via reference, no copy constructor whether implicit or explicitly defined will be called.

A Copy constructor is called when while defining (memory is not allocated yet) , you are assigning value to the object ex

A obj = a;

Assignment operator will be called, when the object is already defined (memory already allocated) and you want to change the fields of the object.

Upvotes: 1

Sergei Tachenov
Sergei Tachenov

Reputation: 24909

The easiest way to understand this, at least for me, is to imagine that you work with pointers, not references:

int* A::setb()
{
    return &b;
}

Now if you do this:

*(a.setb())=5;

It becomes clear what happens. References do exactly the same thing, but without all that *& mumbo-jumbo. Your assignment/copy constructors have nothing to do with this whatsoever. Now, if your field wasn't int, but of some custom type, then the assignment operator of that type would be called. You could do whatever you want to in that assignment.

One interesting trick is that your setb may return a “smart reference” type that actually updates b, but may do something more:

class TwoIntsRef {
public:
    TwoIntsRef(int &a, int &b) :
        a(a),
        b(b)
    {}
    TwoIntsRef& operator=(int c)
    {
        cout << "TwoIntsRef Assignment called" << endl;
        a = c;
        b = c;
        return *this;
    }
private:
    int &a;
    int &b;
};

And then you do this:

TwoIntsRef A::setb()
{
    return TwoIntsRef(b, c);
}

And this:

a.setb() = 5;

Now it sets both b and c.

This is actually a very useful trick that may do a lot of things. In one of my projects I had to port legacy code that relied heavily on Big Endian byte order. To make it work on Little Endian hardware I had to replace all memory access with smart references that would swap bytes automatically. Not a very efficient way, but the only one that would work in that particular project.

Upvotes: 2

Related Questions