overloaded assignment operator and copy constructor.

Discussion in 'C++' started by sam_cit@yahoo.co.in, Aug 22, 2007.

  1. Guest

    Hi Everyone,

    I was just wondering, about the overloaded assignment operator for
    user defined objects. It is used to make sure that the following works
    properly,

    obj1 = obj;

    so the overloaded operator function performs the necessary copy of
    obj's member in to obj1. Can't the same be done using copy
    constructor? If so, then what is the difference between both the
    mechanisms.

    Thanks in advance!!!
    , Aug 22, 2007
    #1
    1. Advertising

  2. On Aug 22, 3:56 pm, wrote:
    > Hi Everyone,
    >
    > I was just wondering, about the overloaded assignment operator for
    > user defined objects. It is used to make sure that the following works
    > properly,
    >
    > obj1 = obj;
    >
    > so the overloaded operator function performs the necessary copy of
    > obj's member in to obj1. Can't the same be done using copy
    > constructor? If so, then what is the difference between both the
    > mechanisms.
    >
    > Thanks in advance!!!


    assignment operator is "assignment operator", copy constructor is a
    "constructor". both have different semantics.

    class X { };

    int main()
    {
    X x;
    X y = x; //invokes copy constructor, since y is getting constructed
    y = x; // invokes copy assignment operator, since y already exists
    and is merely getting assigned.
    }

    -N
    Neelesh Bodas, Aug 22, 2007
    #2
    1. Advertising

  3. * :
    > Hi Everyone,
    >
    > I was just wondering, about the overloaded assignment operator for
    > user defined objects. It is used to make sure that the following works
    > properly,
    >
    > obj1 = obj;
    >
    > so the overloaded operator function performs the necessary copy of
    > obj's member in to obj1. Can't the same be done using copy
    > constructor? If so, then what is the difference between both the
    > mechanisms.


    Ah, good question.

    First, about the difference. A constructor is used to convert raw and
    possibly random bits to a valid instance. An assignment operator is
    used to change the value of an existing instance, and that might entail
    deallocating storage that the existing instance has a pointer to.

    E.g., consider -- while disregarding optimizations --

    std::string s( "blah blah" ); // Constructor, allocates storage.
    s = "Foo bar"; // Assignment, deallocates + allocates new storage.

    The constructor can't make any assumptions about the raw storage it's
    handed, and in particular it can't assume that there's a valid pointer
    in there. The assignment operator, on the other hand, must make such
    assumptions, depending on the type. Conceptually the assignment
    operator has to do the job of first destructing the current object and
    then copy constructing a new object.

    First, positive, this thinking means it's simply Wrong(TM) to express
    construction in terms of assignment: it's positive because it's so easy
    to see that anyone can grok it when pointed out, that assignment is
    /more/ than construction, therefore, construction should not be
    expressed in terms of assignment. Yet some professionals (in the sense
    of being paid by an employer) have done that, and even imposed it on
    others by making it part of some in-house architecture or overall
    application design. It's an easy trap to fall into when your experience
    is primarily with some other language where that makes sense, but in C++
    it leads to horribly complicated and bug-ridden code, so don't do it.

    Negative, this thinking leads naturally to a Very Dangerous(TM) way of
    expressing assignment in terms of destruction and construction, which
    seems to be rediscovered by every programmer learning C++:

    MyType& operator=( MyType const& other )
    {
    this->MyType::~MyType(); // Destruct, leaving raw bits.
    ::new( this ) ( other ); // In-place copy construct.
    return *this;
    }

    One reason it's very dangerous is that the copy construction just may
    fail, throwing an exception, and in that case the current instance has
    already been destructed, oops. Another reason it's very dangerous is
    that when this operator is called on an object of a type derived from
    MyType, it changes the the dynamic type of the object (oops)! Which
    means it effectively imposes a requirement on derived classes to not
    call MyType's copy assignment operator, on pain of Undefined Behavior,
    without that requirement being enforced by the compiler.

    However, while the above is Very Dangerous, it leads in just two small
    steps to the common idiom for implementing assignment in terms of copy
    construction. Namely, instead of destructing the current instance, copy
    construct into a completely new instance, and then /swap/ the contents
    with the current instance. This requires a swap operation for the type:

    MyType& operator=( MyType const& other )
    {
    MyType temporary( other ); // Copy construct into new instance.
    swap( other ); // Swap contents with new instance.
    }

    Here, when the temporary goes out of scope it's destructed in the normal
    way, deallocating any buffers etc. that the current instance may have
    had, now (after the swap) managed by the temporary.

    If swap and the destructor provide the no-throw exception guarantee,
    then this is also exception safe.

    And the code can be further simplified (the second step) to just

    MyType& operator=( MyType other )
    {
    swap( other );
    }

    Which is the common idiom. It's not always the best way to implement
    assignment. But in the absence of strong reasons not to do it this way,
    it should be your default implementation: always, if practical (and
    since the code is so simple it's nearly always practical) implement
    assignment in terms of copy construction, swap and destruction.

    Cheers, and hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Aug 22, 2007
    #3
  4. * Alf P. Steinbach:
    >
    > MyType& operator=( MyType const& other )
    > {
    > MyType temporary( other ); // Copy construct into new instance.
    > swap( other ); // Swap contents with new instance.


    Oops, copy typo, should be "swap( temporary )".


    > }




    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Aug 22, 2007
    #4
  5. In message <>,
    Neelesh Bodas <> writes
    >On Aug 22, 3:56 pm, wrote:
    >> Hi Everyone,
    >>
    >> I was just wondering, about the overloaded assignment operator for
    >> user defined objects. It is used to make sure that the following works
    >> properly,
    >>
    >> obj1 = obj;
    >>
    >> so the overloaded operator function performs the necessary copy of
    >> obj's member in to obj1. Can't the same be done using copy
    >> constructor? If so, then what is the difference between both the
    >> mechanisms.
    >>
    >> Thanks in advance!!!

    >
    >assignment operator is "assignment operator", copy constructor is a
    >"constructor". both have different semantics.
    >
    >class X { };
    >
    >int main()
    >{
    > X x;
    > X y = x; //invokes copy constructor, since y is getting constructed
    > y = x; // invokes copy assignment operator, since y already exists
    >and is merely getting assigned.


    Not always "merely". Assignment also involves disposing of the previous
    contents.

    >}
    >
    >-N
    >


    --
    Richard Herring
    Richard Herring, Aug 22, 2007
    #5
  6. terminator Guest

    On Aug 22, 1:56 pm, wrote:
    > Hi Everyone,
    >
    > I was just wondering, about the overloaded assignment operator for
    > user defined objects. It is used to make sure that the following works
    > properly,
    >
    > obj1 = obj;
    >
    > so the overloaded operator function performs the necessary copy of
    > obj's member in to obj1. Can't the same be done using copy
    > constructor? If so, then what is the difference between both the
    > mechanisms.
    >
    > Thanks in advance!!!


    constructors are -say philosofically- invoked on newly allocated
    objects who do not carry any valid data, but assignment happens for
    previously constructed objects that contain valid -though not
    interesting - data. Thus an assignment operator might need to get read
    of rubish data in some cases -often pointeriod types - while
    constructors generally need not destroy anything before copying
    existing data to a new location.

    regards,
    FM.
    terminator, Aug 22, 2007
    #6
  7. Guest

    > > MyType& operator=( MyType const& other )
    > > {
    > > MyType temporary( other ); // Copy construct into new instance.
    > > swap( other ); // Swap contents with new instance.

    >



    Sorry, I cannot understand what does it mean swap?

    For example, while cannot we do:

    MyType& operator=(MyType const& other)
    {
    swap(other);
    return *this;
    }

    Please, can you describe (for example) such situation:

    class MyClass
    {
    int* pArray; /pointer to array, need allocation memory
    /...
    }

    what's copy constructor, operator= and swap?
    , Aug 24, 2007
    #7
  8. * :
    >>> MyType& operator=( MyType const& other )
    >>> {
    >>> MyType temporary( other ); // Copy construct into new instance.
    >>> swap( other ); // Swap contents with new instance.

    >
    >
    > Sorry, I cannot understand what does it mean swap?


    <url: http://www.thefreedictionary.com/swap>.



    > For example, while cannot we do:
    >
    > MyType& operator=(MyType const& other)
    > {
    > swap(other);
    > return *this;
    > }


    Because here "other" is const.


    > Please, can you describe (for example) such situation:
    >
    > class MyClass
    > {
    > int* pArray; /pointer to array, need allocation memory
    > /...
    > }
    >
    > what's copy constructor, operator= and swap?


    You don't need to define them if you just do

    class MyClass
    {
    std::vectory<int> myArray;
    //...
    };

    instead of dealing with raw arrays and pointers.

    Your C++ textbook should explain constructors, assignment operators and
    (hopefully) swap. If it doesn't, get yourself a better book. Which
    book are you using?


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Aug 24, 2007
    #8
  9. terminator Guest

    On Aug 25, 12:19 am, wrote:
    > > > MyType& operator=( MyType const& other )
    > > > {
    > > > MyType temporary( other ); // Copy construct into new instance.
    > > > swap( other ); // Swap contents with new instance.

    >
    > Sorry, I cannot understand what does it mean swap?
    >
    > For example, while cannot we do:
    >
    > MyType& operator=(MyType const& other)
    > {
    > swap(other);
    > return *this;
    >
    > }
    >
    > Please, can you describe (for example) such situation:
    >
    > class MyClass
    > {
    > int* pArray; /pointer to array, need allocation memory
    > /...
    >
    > }
    >
    > what's copy constructor, operator= and swap?


    The term 'swap' means exchanging the values of two objects.A general
    solution for swappig two objects is the famuse triple assign method:

    temp=other;
    other=me;
    me=temp;

    but in some cases there exists a short cut and we do not need to pay
    that much for the swap;In such cases a swap is normally performed much
    faster and easier than an assignment ,and assignment is defined in
    terms of swap rather than the vice versa.(pointeroids , string &
    reference counting are best examples .):

    struct my_string{
    public:
    my_string():str(null),sz(0){};
    my_string(const char *const s){/* build from null-terminated c-
    style string and literals*/
    sz=strlen(s);
    str=new char[sz];
    memcpy(str,s,sz);
    };
    my_string(my_string& s):str(new char[s.sz]),sz(s.sz)
    {memcpy(str,s.str,sz);};

    bool swap(my_string& right){
    if (right==*this) return false;

    //swap str:
    char* temp=str;
    str=right.str;
    right.str=temp;

    //swap sz:
    sz^=right.sz;
    right.sz^=sz;
    sz^=right.sz;

    return true;
    };

    bool operator==(const my_string& right){
    if(sz!=right.sz) return false;
    return 0==memcmp(str,right.str,sz);
    };

    const my_string& operator=(my_string other){
    swap(other);
    return *this;
    };

    ~my_string(){delete[] str;};

    private:
    char* str;
    size_t sz;
    ....//concate , find , cstr , size ... etc
    };

    this is not the best approach to design strings but it shares the
    common swap/copy/assign method of dynamic memory management with
    better solutions.If you defined swap in terms of assignment,allocation/
    deallocation(new/delete) of memory would happen three times per
    swap.But now swap needs no allocation/deallocation and as you can
    see,assignment needs exert a deallocation in either case (destruction
    of auto variable or explicit delete).

    regards,
    FM
    terminator, Aug 29, 2007
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    12
    Views:
    2,219
    Howard
    Jun 16, 2005
  2. Replies:
    10
    Views:
    547
    Heinz Ozwirk
    Jul 5, 2005
  3. Henrik Goldman
    Replies:
    2
    Views:
    427
    Andrey Tarasevich
    Dec 26, 2006
  4. saxman
    Replies:
    2
    Views:
    418
    saxman
    Jun 12, 2007
  5. harry
    Replies:
    6
    Views:
    965
Loading...

Share This Page