constructor and the assignment operator - c++

Can I write a copy constructor through the assignment operator? Like this:
A::A(const A * a) {
*this = a;
}
A &A::operator=(const A * a) {
delete str;
str = new char[strlen(a->str)+1];
strcpy(str, a->str);
return *this;
}
Still want to clarify whether if I do A * a in the above example, because samples from different sites A & a. C This pops up a question that should return the assignment operator:
A &A::operator=(const A * a)
or
A * A::operator=(const A * a)
General question: Is my code right above?

The best solution is to make str be a std::string and then you don't need to write your own copy constructor OR copy assignment operator.
But let's say you have to write your own for non-obvious reasons you can't share with us.
In that case, a typical approach to provide some exception safety is to implement a nothrow swap function, and then implement copy assignment in terms of copy construction + swap (the opposite of what you're proposing, but provides much better exception safety for the copy assignment)

Both of them have different signature:
A::A(const A &a);
A &A::operator=(const A &a);
What you are writing is not copy constructor nor assignment operator.
Look for copy-and-swap idiom, this is what allows you to write copy assignment in terms or copy construction.

Related

Copy constructor, assignment operator, and destructor code duplication

I understand the need for deep copies, and to ensure my code behaves as desired, I am writing a copy ctor, assignment operator, and dtor for my class.
However, it seems to me that in every case, an assignment operator has to do first what the destructor does (deallocate any dynamically allocated memory, to prevent memory leaks), and then what the copy constructor does (make deep copies of all dynamically allocated data and copy those into the instance being constructed).
Is there a case where an assignment operator should conceptually do something other than the following?
class SomeClass{
//member data, copy ctor, dtor
SomeClass& operator=(SomeClass const& rhs){
//what the destructor does
//what the copy constructor does
}
};
The code is practically identical, and seems like a waste of time to rewrite. Other than invoking the destructor directly at the beginning of the assignment operator, I can't think of a way to reuse the copy constructor code I've already written, since I believe doing something like
*this=rhs
would only recursively invoke the assignment operator, since techinically, "this" has already been constructed.
As mentioned in the comments, your concerns about code duplication is addressed by applying the copy-and-swap idiom:
class SomeClass{
//member data, copy ctor, dtor
SomeClass& operator=(SomeClass rhs){
swap(*this, rhs);
return *this;
}
friend void swap(SomeClass& first, SomeClass& second) {
using std::swap;
swap(first.data, second.data);
//... etc. for other data members
}
};
You have to implement the additional swap function, but your copy constructor and destructor code is reused in a natural way. The copy constructor is used when the source of the assignment is passed to the assignment operator, and the destructor is reused when the argument is destructed when the assignment operator returns.

C++: call copy assignment in copy constructor

OK,I am reading "effective C++" and item 12 says please don't call copy assignment in copy constructor.But after I try to do this, it does work. So I want to ask why, I can't reuse the copy assignment code in copy constructor?
Assume you use copy-assignment operator in copy-constructor. Then you lose the ability to implement copy-and-swap idiom for assignment operator:
struct A
{
A (const A &a)
{
*this = a; // Assignment to a not yet constructed object is not well
}
A &operator=(A a) // Pass by value
{
// ...
}
};
A a1, a2;
a1 = a2; // Infinite recursion!
It's not possible and infinite recursion will occur.
A constructor creates a new object; an assignment operator modifies an existing object. You can't use an assignment operator to create a new object: it doesn't know how to do that, even if it seems to work in simple cases.

What is the correct implementation of move constructor (and others)?

I have a simple class which contains an std::vector, and I would like to benefit from move semantics (not RVO) when returning the class by value.
I implemented the move constructor, copy constructor and copy assignment operators in the following way:
class A
{
public:
// MOVE-constructor.
A(A&& other) :
data(std::move(other.data))
{
}
// COPY-constructor.
A(const A& other) :
data(other.data)
{
}
// COPY-ASSIGNMENT operator.
A& operator= (const A& other);
{
if(this != &other)
{
data = other.data;
}
return *this;
}
private:
std::vector<int> data;
};
Are the above implementations correct?
And an other question: do I even have to implement any of these members, or are they auto-generated by the compiler? I know that the copy-constructor and the copy-assignment operator are generated by default, but can the compiler auto-generate the move constructor as well? (I compile this code both with MSVC and GCC.)
Thanks in advance for any suggestions. (I know that there already are some similar questions, but not for this exact scenario.)
They're all unnecessary for this class[*], since it would have implicit ones if you didn't declare any of them.
Your constructors are fine. So the following code ostensibly calls the move constructor:
A f() { return A(); }
A a = f(); // move construct (not copy construct) from the return value of f
In fact move-elision might kick in, in which case only the no-args constructor is actually called. I assume you plan to provide some constructors other than copy and move ;-)
Your copy assignment is fine, it differs from the implicit one only in that it has the self-assignment check, which the implicit one would not. I don't think we should have the argument whether a self-assignment check is worth it or not, it's not incorrect.
You haven't defined a move-assignment operator. Given that you defined the others, you should have done, but if you get rid of the rest it's implicit[*]. The move assignment operator (whether user-defined or implicit) is what ensures that the following code will move instead of copying:
A a;
a = f();
[*] On a completed C++11 implementation, of which so far none exist. You can check on a per-compiler basis whether this feature is implemented yet, and probably you'll end up with some horrible #define shenanigans until MSVC does.
For this exact scenario, You don't need to declare any move/copy/assignment functions. Compiler will generate correct defaults.

Why assignment operator is used for deep copy and who calls it

During deep copy we are writing overloaded copy constructor and assignment operator.
May i know why we have to write the overloaded assignment operator because we doing the same in overloaded copy constructor(except some check and return this).
Who is calling assignment operator
Follow the Rule of Three:
If you need to write an copy constructor for your class, You also should write the Copy assignment operator and Destructor.
Copy Assignment operator and Copy Constructor both are called Copying functions. They basically help in getting a new copy of an object from an existing object. They both are separate entities invoked in different scenarios. So, just as in case of Copy constructor you ensure that you make deep copies of all pointer members and not just shallow copies, same would applies for copy assignment operator.
An Code Example:
class MyClass obj1, obj2;
class MyClass obj3(obj1); //Calls Copy Constructor
obj1 = obj2; //Calls Copy Assignment Operator
The assignment operator is used if you do this:
MyType my1, my2;
my1 = my2; // same as: my1.operator=(my2);
The copy constructor and the assignment operator usually have very similar code, but if done properly (initializer lists) should be coded differently, used differently, and perform differently.
The copy constructor should use initializer lists. This is used for creating a new vector object that is the same as one already existing.
vector::vector(const vector& b)
:size(b.size),
capacity(b.capacity),
data(new TYPE[size])
{
//there should be minimal code here
//I'm skipping copying the data, because doing it right
//is hard and beside the point
}
vector seven;
seven.push_back(7);
vector seven_copy(seven); //make a new one, same as old
The assignment operator is probably exactly what you have. This is used to reassign an already existing vector object to be the same as one already existing
vector& vector::operator=(const vector& b)
{
//carefully written so self assignment doesn't crash.
TYPE* temp = new TYPE[b.size];
//I'm skipping copying the data, because doing it right
//is hard and beside the point
delete [] data;
//all exceptions that can be thrown, have, so it's safe to modify members now
data = temp;
size = b.size;
capacity = b.capacity;
return *this;
}
vector nine;
nine.push_back(9);
nine = seven; //make an old one the same as another old
It should be noted that the move constructor and move assignment may look vaguely similar, but should probably be different as well.
vector::vector(vector&& b)
:size(b.size)
capacity(b.capacity)
data(b.data) //different!
{
b.data = nullptr;
}
vector& operator=(vector&& b)
{
//since b.data is tied to b.size and b.capacity, it's safest to just swap
//so if someone calls b.push_back() after, it's all still safe.
std::swap(size, b.size);
std::swap(capacity, b.capacity);
std::data(data, b.data);
return *this;
}

Class basic operators

Is it necessary to have a copy constructor, destructor and operator= in a class that have only static data member, no pointer
class myClass{
int dm;
public:
myClass(){
dm = 1;
}
~myClass(){ } // Is this line usefull ?
myClass(const myClass& myObj){ // and that operator?
this->dm = myObj.dm;
}
myClass& operator=(const myClass& myObj){ // and that one?
if(this != &myObj){
this->dm = myObj.dm;
}
return *this;
}
};
I read that the compiler build one for us, so it is better to not have one (when we add a data member we have to update the operators)
If you can't think of anything for the destructor to do, you almost certainly don't need to define it, with the exception of a virtual destructor in a base class. And if you don't need a destructor, you almost certainly don't need to define the copy constructor and assignment operator, and should not do so, as it's easy to get them wrong.
No. The compiler will automatically copy-construct, destruct, and assign all data members automatically. This means that if you have a class where they're all provided, you don't need to write these. I think it's better design to write operators on a per-member basis anyway.
The compiler would provide those itself. By default the copy constructor / assignment operator would copy / assign all members (and base parts of the object if the class is derived), and the destructor does nothing (invokes the destructor of all members / bases, but this is something you can't change even if you provide your own - that happens after the body of the user-defined destructor is exited).
So in this case it is completely unnecessary. All you can achieve is to introduce bugs in the code (e.g you add another member, but forget to update the copy constructor to copy that as well).
myClass& operator=(const myClass& myObj){ // and that one?
if(this != &myObj){
this->dm = myObj.dm;
}
return *this;
}
I don't think you should take "check for self-assignment" dogmatically. Does anything bad happen when you assign an int to itself (even indirectly)?
int a = 10;
int& ref = a;
a = ref;
Avoiding self-assignment is only relevant if the assignment operator first destroys the resources currently held and then creates new ones from the object on the right-hand side. Then it would be a disaster to find out that you have actually indirectly destroyed the right-hand object too.
But even in that case, it would be better to first create the copy of the right-hand side and then destroy the contents of the left-hand side, in which case self-assignment is no problem (except potentially inefficient). For a good way to implement this, Google for copy and swap idiom.