'operator=' and the 'copy constructor'

Hey,

I was programming a very simple class, but while creating it I ran into a couple of question marks. In particular, question marks concerning the assigment operator (=) and the copy constructor.

For the examples I am going to give, I'll use the following class definition:
[code]
class A
{
A();
A(A&);
~A();

A& operator= (A&);
};
[/code]

My class allocates some memory dynamically, so I have to implement my own copy constructor, to make sure that each instance uses a private bit of memory. Then I realised that I should probably implement operator= as well.

And about here and now I started getting confused.

Question 1: Am I correct in assuming the copy constructor is only used when explicitly writing:
[code]
A a1;
[color=Blue]A a2(a1);[/color]
[/code]

Question 2: When using the following code:
[code]
A a1;
A a2;

a1 = a2;
[/code]
This would cause the default operator= to be called, if I did not supply my own implementation? In other words, it would never call anything else but an operator= (in particular, never the copy-constructor?).

Question 3: Implementing both the operator=, A(A&) and ~A() results in a lot of double code.
(*) operator= and ~A() both need to clean up the allocated memory
(*) operator= and A(A&) both copy the members of the A& instance
I turned these blocks of code into private methods, so as to have the code centralized as much as possible. To elaborate with a piece of code:
[code]
A& operator= (A& a)
{
freeMemory();
fromObject(a);
}

A::A(A& a)
{
fromObject(a);
}

A::~A()
{
freeMemory()
}
[/code]
Where freeMemory and fromObject are private methods of A.

The question (finally): Is this a decent way of programming? Should I redesign something?
Or is there some other method, which leads me to Question 4

Question 4: Is there a way, rather than creating new private methods like freeMemory and fromObject, to call the Destructor for the clean-up and copy-constructor for the initialization? Exempli gratia:
[code]
A& A::operator= (A& a)
{
~A(); //Call destructor
A(a); //Call copy-constructor
}
[/code]
(Or something in the neighbourhood)

Well, I've bored enough people already with this lenghty post.
Thanks to anyone who bore with me till this line, and I appreciate the others who didn't make it here for trying ;)

Best Regards,
Richard

The way I see it... Well, it's all pretty blurry

Comments

  • : Hey,
    :
    : I was programming a very simple class, but while creating it I ran
    : into a couple of question marks. In particular, question marks
    : concerning the assigment operator (=) and the copy constructor.
    :
    : For the examples I am going to give, I'll use the following class
    : definition:
    : [code]:
    : class A
    : {
    : A();
    : A(A&);
    : ~A();
    :
    : A& operator= (A&);
    : };
    : [/code]:
    :
    : My class allocates some memory dynamically, so I have to implement
    : my own copy constructor, to make sure that each instance uses a
    : private bit of memory. Then I realised that I should probably
    : implement operator= as well.

    [blue]That is correct. As a rule of thumb: if your class needs to implement either the copy constructor or the assignment operator or a destructor, it needs all three of them.[/blue]

    :
    : And about here and now I started getting confused.
    :
    : Question 1: Am I correct in assuming the copy constructor is only
    : used when explicitly writing:
    : [code]:
    : A a1;
    : [color=Blue]A a2(a1);[/color]
    : [/code]:

    [blue]Either that or

    A a2=a1;

    It means exactly the same thing, as long as the other class is passed on the same line the object is declared on.[/blue]

    : Question 2: When using the following code:
    : [code]:
    : A a1;
    : A a2;
    :
    : a1 = a2;
    : [/code]:
    : This would cause the default operator= to be called, if I did not
    : supply my own implementation? In other words, it would never call
    : anything else but an operator= (in particular, never the
    : copy-constructor?).

    [blue]Correct, it will only call the default constructor.[/blue]

    : Question 3: Implementing both the operator=, A(A&) and ~A() results
    : in a lot of double code.
    : (*) operator= and ~A() both need to clean up the allocated memory
    : (*) operator= and A(A&) both copy the members of the A& instance
    : I turned these blocks of code into private methods, so as to have
    : the code centralized as much as possible. To elaborate with a piece
    : of code:
    : [code]:
    : A& operator= (A& a)
    : {
    : freeMemory();
    : fromObject(a);
    : }
    :
    : A::A(A& a)
    : {
    : fromObject(a);
    : }
    :
    : A::~A()
    : {
    : freeMemory()
    : }
    : [/code]:
    : Where freeMemory and fromObject are private methods of A.
    :
    : The question (finally): Is this a decent way of programming? Should
    : I redesign something?

    [blue]If you have a lot of member variables that needs to be copied/deleted, then sure, it might be a good idea. It will prevent you from forgetting to copy/delete a variable in one of them while remembering it in the other. Those private functions should probably be made "inline" though, to speed things up a bit.

    Just don't forget to add this to the top of your assignment operator:

    [code]if (this == &a)
    {
    return *this;
    }[/code]

    This will protect your code from [link=http://www.parashift.com/c++-faq-lite/assignment-operators.html#faq-12.1]"self assignment"[/link].[/blue]


    : Or is there some other method, which leads me to Question 4
    :
    : Question 4: Is there a way, rather than creating new private methods
    : like freeMemory and fromObject, to call the Destructor for the
    : clean-up and copy-constructor for the initialization? Exempli gratia:
    : [code]:
    : A& A::operator= (A& a)
    : {
    : ~A(); //Call destructor
    : A(a); //Call copy-constructor
    : }
    : [/code]:
    : (Or something in the neighbourhood)

    [blue]No, you should never call the destructor, that will lead to fatal bugs. Nor should you call the copy constructor, that will only create a new dummy object which won't be used. [/blue]

    : Well, I've bored enough people already with this lenghty post.
    : Thanks to anyone who bore with me till this line, and I appreciate
    : the others who didn't make it here for trying ;)
    :
    : Best Regards,
    : Richard
    :
    : The way I see it... Well, it's all pretty blurry
  • :
    : [blue]Just don't forget to add this to the top of your assignment operator:
    :
    : [code]: if (this == &a)
    : {
    : return *this;
    : }[/code]:
    :
    : This will protect your code from
    : [link=http://www.parashift.com/c++-faq-lite/assignment-operators.html
    : #faq-12.1]"self assignment"[/link].[/blue]
    :

    Thanks for the hint. I didn't for one second think about that possibility.

    : [blue]No, you should never call the destructor, that will lead to
    : fatal bugs. Nor should you call the copy constructor, that will only
    : create a new dummy object which won't be used. [/blue]
    :

    I figured it wouldn't be possible, but I still was curious to know for sure.
    Best Regards,
    Richard

    The way I see it... Well, it's all pretty blurry
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories