Which to prefer, Copy Constructor or object assignment? - c++

There is a class A with 2 objects A1 and A2.
Now to assign the member values of A2 to A1, I could have used either simply A1 = A2,
or use a copy constructor instead like :-
A (A &A2)
{
this.m = A2.m;
this.n = A2.n;
}
So, I want to know that which one is better and where which option is suitable or is there really any difference between them ?

Firstly, you would need to do this->m, because this is a pointer.
Secondly, a copy constructor should usually take a const A&.
Thirdly, if you need to implement a copy constructor, you probably also need to implement the assignment operator. In this case, I'm not sure you actually need to implement either (just default them).
Fourthly, the copy constructor and assignment operator are used in different situations:
A A1 = A2; // Copy constructor
A1 = A2; // Assignment
You should provide both.
Fifthly, you could better write your constructor with a member initialisation list:
A(const A& A2)
: m(A2.m), n(A2.n)
{ }

It depends on what you want to achieve.
If you want to make a shallow copy of your object, then a plain assignment is enough.
However, if you are in a case where your object manages pointers (calls new in constructor and delete in destructor), then you need to use the copy constructor and create a copy of each field, otherwise you could be accessing pointers of invalid state.

Related

c++ (why) does move constructor delete operator=

I have a vector with structs
Struct S {
S( double a, double b ) : a_(a), b_(b) {}
double a_;
double b_;
S(S&&) = default; //ADDED
}
and I use emplace back to add instances of s to the vector
v.emplace_back( x, y );
Since it doesn't seem to be guaranteed that compilers will add a move constructor, I thought there is no harm in adding a default move constructor, so I added the line commented as ADDED.
However, this seemed to have disabled the operator= as I get the compile error
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/stl_algo.h:868: error: use of deleted function ‘S& S::operator=(const S&)’
*__result = _GLIBCXX_MOVE(*__first);
^
I dont understand why that is the case. Is my implementation of S(S&&) the wrong way to do it?
EDIT:
The error is thrown when using erase-remove
v.erase(std::remove_if(v.begin(), v.end(), deleteIf), v.end());
A default copy assignment operator will be automatically provided (performing a memberwise copy) unless the class declares a copy assignment operator, deletes the copy assignment operator, or declares a move operation. The reason for this is that the compiler assumes that if you declare any move operation, it is likely that your class holds data which should not be copied, and so it forces you to implement the copy assignment operator yourself, in an attempt to enforce the Rule of Five.
There's an excellent chart showing when default constructors and assignment operators are provided in this slideshow, slide 30.
Some older implementations of STL containers use the assignment operator when they resize the underlying containers. To resize, they allocate memory, default construct the initial objects, copy the objects over to the new container by using the assignment operator, and then release the previous objects.
On a related topic, if you are going to make an object Move-Constructible, you should also make it Move-Assignable.
Since the only data members in your struct are double's - primitive types that don't allocate resources - you don't need a move constructor for this struct.

C++ vector copy assignment, calling which copy mechanism of its elements?

My class A explicitly implements both its copy constructor and its copy assignment.
Which copy mechanism is used when copy assigning a vector of such elements?
Is this:
vector<A> a1, a2(5);
a1 = a2;
going to use A's copy constructor for all new elements of a1, with the elements of a2 as input?
Or is it going to make room in a1 for the elements, then use A's operator= with the elements of a2 as input?
What if a1 isn't empty before the assignment?
Is it even specified?
My class's copy constructor and operator= don't exactly do the same thing (is it bad practice? Mainly testing stuff so far). It looks like the copy constructor is called, but I wonder if it is guaranteed to be that way or if it just happens to be so in this very case.
In this context it will call the copy constructor 5 times. Since a1 is empty, there aren't any elements to assign to. So they need to be copy-constructed.
Generally, it will call whatever mixture of copy/move construction/assignment or deletion is appropriate. All depending on the sizes of the vectors in question, the particular vector operation you are performing, and the value categories of the operands.
It looks like the copy constructor is called, but I wonder if it is guaranteed to be that way or if it just happens to be so in this very case.
It could be guaranteed for the exception-safe swap-based implementation of assignment:
struct SomeClass
{
SomeClass(const SomeClass& other) { ... }
SomeClass(SomeClass&& other) { ... }
// Copy/move construction is performed while initializing the parameter
void operator=(SomeClass other)
{
this->swap(other);
}
void swap(SomeClass& other) { ... }
};
The disadvantage of such an implementation of assignment is that - because of its generality - it is not the most optimal one (for example, it does unnecessary job in case of self assignment).
In general, if exception safety concerns can be rules out, copy assigning to an object can be done faster than destroying it and constructing an in-place copy of the source object. Therefore, you should expect that performance-seeking implementations would perform assignment of objects through assignment rather than copy-construction of their sub-objects wherever possible.

how come invoking a constructor implicitly and invoking a constructor explicitly turns out to be same

I am new to c++.
I was told that invoking a constructor internally or externally are same.
Why is assignment operation not involved in the case of invoking constructor explicitly?
Object A(3) //implicit
Object A = Object(3); //explicit
I think an object will get created when we do Object(3);
So how are these two things turn out to be same?
Take a look at this answer for more on the subject, but assignment operator is invoked when you are dealing with an already existing object. You'll notice similar behaviour for copy constructors:
Object A;
// the following two lines will call the copy constructor
// even if the assignment operator is defined.
Object B = A;
Object C(A);

Why to use copy constructor C++

As i know, when we assign one object is another default copy constructor will be called.
class class1 obj1;
class class2 obj2;
obj1(obj2); //default copy constructor will be called by compiler
So, when should I write explicitly the copy constructor?
In your case the copy-assignment operator will be called, not the copy-constructor. To call the copy-constructor you would have do to e.g.
class1 obj1;
class1 obj2 = obj1; // Invokes the copy-constructor in obj2
A good idea when to write a copy-constructor (or a copy-assignment operator, or a destructor) you can see by reading about the rule of three. In short, if you have any of a destructor, copy-constructor or copy-assignment operator, then you should probably have all of them.
Also, while the compiler will auto-generate copy-constructor and copy-assignment operator for you if you do not provide your own, you have to remember that those auto-generated function will only do a shallow copy. If you have e.g. pointers to memory you allocate in the object, the auto-generated functions will only copy the actual pointer, and not what it points to. This means that after a copy you have two objects both pointing to the same memory. If you delete the pointer in the destructor, and one of the objects are destructed, the other object will still have its pointer, but it will now point to deleted memory.
You will get a default copy constructor when you don't write one, provided you don't add any of the three or five to your class : destructor, copy or move assignment or constructor.
Sometimes this does the right thing. For example, if you just need a shallow copy, or if the member's corresponding functions fo the right thing, for example smart pointers.
If an object exist prior to the assign, then it does not involve a construction but the assignment operator, signatures are:
T& operator=( T const & ); // from l-value ref
T& operator=( T && ); // from r-value ref, since c++11
A frequent strategy is to write the assignment operator as the idiom "copy and swap" :
T& operator=( T const & o ) {
T val( o ); // you need to write the copy ctor
swap(*this,o); // you need to write the swap
return *this;
}
T& operator=( T && o ) {
T val( std::move(o) ); // you need to write the move ctor
swap(*this,o); // you need to write the swap
return *this;
}
The c++11 version of that strategy
T& operator=( T o ) noexcept { // copy done before the operator that can be noexcept ( swap have to too)
swap(*this,o); // you need to write the swap
return *this;
}
In some cases you will find that the way your objects should be copied is not trivial.
If you consider the class :
class Car {
string BrandName;
int NumberOfPassenger;
}
Then it is clear that when you'll be copying two objects, you'll simply want to copy them member by member. There's nothing special to do here so the defaut copy constructor will work just fine.
But imagine that the class is instead :
class Car {
string BrandName;
int NumberOfPassenger;
Mechanics EngineeringStuff;
}
Here Mechanics is a reference type. What the copy constructor will do is simply copying the reference to the new object, so both cars - car1 and car2 - will share the same EngineeringStuff. But a more natural behaviour would be to allocate manually a new Mechanics object when performing the copy, so the cars don't share the same wheels, motors etc...
More generally, it's usually when you have to deal with reference types or certain kind of business logic that you will need to explicitly write your copy constructor.

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.