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
:
: 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