Why *this=door is correct? - c++

Door::Door(const Door& door)
{
*this = door;
}
I am very confused with this copy constructor. For me, it does not make sense to use *this=door, but rather
Door::Door(const Door& door)
{
this->color = door.color;
this->destination = door.destination;
}
Can you explain why *this=door is correct?
EDIT
As it is suggested, I need to overload = for the class. So I got something like
const Porte& operator =(const Porte& source)
{
this->color = door.color;
this->destination = door.destination;
}
So I am right to use *this=door now. Why isn't it rather this=door instead?

It invokes Door::operator=(Door const &other).
If that operator is explicitly implemented, it does whatever the implementation says it does. If it's implicitly generated, it simply copies the values of all members.

this is a prvalue pointer. Pointers do not have members and correspondingly you cannot apply the member access operator on a pointer.
this.color = door.color;
this.destination = door.destination;
To access the pointed object through a pointer, you must indirect through the pointer using an indirection operator. In the first program, the unary * is used which is the indirection operator.
There is also a member access indirection operator -> which is a shorthand for indirecting through a pointer and accessing member of the pointed object. As such, you could write:
this->color = door.color;
this->destination = door.destination;
The first example instead uses the assignment operator to do the same thing.
Neither of these is something that I would recommend. Best way to implement a copy constructor is in order of preference. If the first one is not applicable, then use the next and so on:
If you don't need to, don't declare copy constructor at all and use the implicitly generated one.
Define the constructor as explicitly defaulted (or deleted).
Initialise the members and leave the constructor body empty.
why it is not this=door instead?
Because it is not supposed to assign the pointer. It is supposed to assign the pointed object. As I explained above, you must indirect through the pointer (using indirection operator) in order to access the pointed object.
Besides, this is an rvalue, so it cannot be assigned.

Related

Can I use the = operator to assign one object's values to another object, without overloading the operator?

this was a recent T/F question that came up in my cs course that I found a bit confusing.
The textbook states:
The = operator may be used to assign one object's data to another object, or to initialize one object with another object's data. By default, each member of one object is copied to its counterpart in the other object.
The question verbatim was:
You cannot use the = operator to assign one object's values to another object, unless you overload the operator. T/F?
Judging from that particular paragraph of the textbook, I answered false. However, it turns out the quiz answer was actually true.
When I looked up the question online, I saw other sources listing the answer as "false" as well. Granted, these were just generic flashcard / quiz websites, so I don't put much stock in them.
Basically, I'm just curious what the real answer is for future studying purposes.
P.S.: The textbook later goes on to state: "In order to change the way the assignment operator works, it must be overloaded. Operator overloading permits you to redefine an existing operator’s behavior when used with a class
object."
I feel like this is related and supports the "true" answer, but I'm not really sure.
The statement
” You cannot use the = operator to assign one object's values to another object, unless you overload the operator.
… is trivially false, because you can assign to e.g. an int variable. Which is an object. In C++.
Possibly they intended to write “class-type object”, but even so it's false. E.g. any POD (Plain Old Data) class type object is assignable and lacks an overloaded assignment operator.
However, there are cases where you want or need to prohibit or take charge of assignment.
If you don't implement the assignment operator yourself, the compiler will generate one for you, which will copy the data from the source to the destination, invoking assignment operators of the members of your class where possible/necessary.
This does not work if your class e.g. features const members, and it does not yield the desired result if your class contains pointers to dynamically allocated objects.
So, I would also say that the statement is false.
That's a trick question. The syntactic answer is "false" but the semantic answer is "maybe".
struct Foo
{
int a;
double b;
};
Foo foo1;
Foo foo2;
foo2 = foo1; // Ok in both senses.
struct Bar
{
Bar() : arr(new int[20]) {}
~Bar() { delete [] arr; }
int* arr;
};
Bar bar1;
Bar bar2;
bar2 = bar1; // Ok in syntax not in semantics
// This will lead to UB
In C++, when User-Defined Types such as class and struct are involved then its better to overload operator= for the Type. Using default assignment operator with object of class or struct will involve Shallow Copy. Shallow Copy sometimes lead to undefined behavior when the class or struct objects have dynamically allocated memory inside them.
Appropriately overloading operator= for class and struct types will lead to Deep Copy which is the correct method of assigning an object ObjA to object ObjB (ObjB = ObjA) when ObjA and ObjB are objects of some class or struct and contain dynamically allocated memory inside them.
The = operator may be used to assign one object's data to another object, or to initialize one object with another object's data. By default, each member of one object is copied to its counterpart in the other object. This is true when object of class/struct has only static fundamental type of data inside it. Here,
by static it means that all the memory requirement of object is fixed at compile time only.
You cannot use the default = operator to assign one object's values to another object, unless you overload the operator. This is true when object of class/struct has some dynamically allocated memory inside it, possibly by using pointers.
For more reference see:
What is the difference between a deep copy and a shallow copy?
You cannot use the = operator to assign one object's values to another object, unless you overload the operator. T/F?
Ans: F
You can assign one object's values to another object without overloading = operator, as compiler by default defines assignment operator for the class in all case except for below
you have explicitly declared a copy-assignment operator (for class X an operator = taking X, X& or const X&) )
there is a member in your class that is not assignable (such as a reference, a const object or a class with no or inaccessible assignment operator)
But you need to understand why it becomes mandatory to overload the assignment operator in case you are having user defined members or having dynamic memory allocation,for this read concept of shallow and deep copy

Overloading the = Operator in a Class

I've built a quaternion class and want to know if I should overload the = operator. Is there any greater benefit to overloading this? What are the detriments to not overloading it?
If I do overload it it will be done like this:
if (this != &Input)
{
w = Input.w;
x = Input.x;
y = Input.y;
z = Input.z;
Normalise();
CalculateMatrix();
}
return *this;
I've built a quaternion class and want to know if I should overload
the = operator. Is there any greater benefit to overloading this? What
are the detriments to not overloading it?
You haven't shown your class definition. Without this one would not be able to comment. Typically, if your class does (not) have ownership of any indirect members (pointers), then the default generated copy constructor / assignment operator is adequate. These defaults performs memberwise copy (copies every member) by value. If one of your members happen to be a pointer, this would be copied by value too (and the rhs/source of the assignment would still contain the original pointer). The problem arises during first deletion of the either source/destination of assignment, when one of the objects delete the "owned" memory, whilst the other is still holding onto it (via indirect member).

Why can't we use pass by pointer in copy constructor in c++?

I know the general syntax of copy constructor in c++ would take reference.
But, my doubt is what happens if we use pointer type instead of reference? Why don't we use pass by pointer mechanism in Copy constructor?
What are the major disadvantages in it?
Passing by references ensures an actual object is passed to the copy constructor, whilst a pointer can have NULL value, and make the constructor fail.
According to the standard, copy constructors taking pointers don't exist:
[C++11: 12.8/2]: A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments (8.3.6). [..]
Pointers are not included because the whole point of references is to "be" aliases for objects, whereas pointers represent indirection. Without delving too far into esoteric details about language design, it's a semantic distinction that makes a lot of sense when you consider the syntactic differences between them.
You can write any constructor you want, and it can take a pointer if you want it to, but it won't be a "copy constructor". It will be probably be really unclear and vague as to ownership semantics, and be unconventional, and be kind of weird, and that's why we don't do it.
It's not unheard of, though; consider this constructor that was the only way to instantiate a file stream in C++ until just three and a bit years ago:
explicit basic_ifstream(const char* s, ios_base::openmode mode = ios_base::in);
Technically, you could write a constructor that takes a pointer (although it's technically not a copy constructor in that case, based on the wording of the spec). However, this prevents you from using non-addressable results. Consider we have a big math class (multiprecision):
bigmath a = 14;
bigmath answer(a * 3);
You can't take the address of the expression a * 3, so you still need a const bigmath & version of the object.
(As Bart says, it also ensures that the object is a "proper object", which isn't going to hurt either - but to me, the above is a stronger argument).
I should perhaps add that the type(s) of constructors you choose to have for your object really depends on what the class does and represents. There are objects where a copy is definitely not "good", and there are other cases, like a bigmath class, where copy constructors are definitely a good thing. For a bigmath class, you'd probably also want a constructor that takes a long integer, a double and a string. In some cases, having a reference doesn't make sense. In some cases, having a const reference doesn't make sense. And in some cases, like I said, having a copy constructor doesn't make sense.
Typically, you can convert a pointer ptr to a reference by adding a dereference *ptr operation. Since the compiler will take the address of that (so that it can pass the reference), it won't add any extra code to use that. But for convenience, if you have a class that you often have pointers to and that you want to make copies of, then it may indeed make sense to have a constructor that takes a pointer. I'm not entirely sure where that would be, of the top of my head.
A copy constructor is where you need the functionality to perform a deep copy or a shallow copy of the object thus we need to pass the reference of the values which are to be copied which acts as a fail safe to avoid junk values or nullptr to create a replica of the requested object. When you use pointers in the parameter, it just becomes a normal constructor.
More detail on this can be found in this article.
According to me the standard of copy constructors use reference but reference and pointer both will give same output but whenever you will assign nullptr to object using reference(TestConstrutor obj2 = nullptr) it will not allow but if you are passing as a pointer, it will work but it will crash because you can not assign null pointer to object.
It will work fine :-
TestConstrutor(const TestConstrutor &obj)
x = obj.x;
y = obj.y; //it will call TestConstrutor obj1(100,200); TestConstrutor obj2 = obj1;
TestConstrutor(const TestConstrutor *obj)x = obj->x;
y = obj->y;// it will call TestConstrutor obj3 = &obj2;
It will not allow :-
TestConstrutor(const TestConstrutor &obj)x = obj.x;
y = obj.y;//TestConstrutor obj2 = nullptr;
It will alow butit will crash :-
TestConstrutor(const TestConstrutor &obj)x = obj.x;
y = obj.y;
TestConstrutor(const TestConstrutor *obj)x = obj->x;
y = obj->y; // TestConstrutor obj2 = nullptr;

Why don't i have to overload the assignment operator in c++?

Here is my code:
class Example {
...declarations/definitions...
};
Example operator + (Example e)
{
Example temp;
...do addition...
return temp;
}
//main
void main()
{
Example a(1,2);
Example b(3,4);
Example c;
c = a+b;
}
Now what confuses me is that I had to overload the + operator for it to work with the vectors but how about the equal '=' sign?? I am assigning one vector to another, shouldn't i be overloading it too?? Or is it provided already to us?
Thanks.
The language provides a default operator= for you automatically if your class is default assignable (for example if it has any reference members it won't be assignable without special work by you). All it does is assign the base and each member individually.
From the wikipedia page:
The default version [of the assignment operator] performs a memberwise copy, where each member is copied by its own copy assignment operator (which may also be programmer-declared or compiler-generated).
If you don't declare a copy-assignment operator in your class, then one is implicitly declared for you (and implicitly defined if you ever use it).
The implicit operator will assign each member of your object, if that's possible; otherwise (if some member is a reference, or const, or has a private or deleted copy-assignment operator) you'll get a compile error.
Similarly, if you don't declare a copy constructor, then you'll get an implicit one, which will copy each member. Your code is using that in operator+, to copy both the argument and the return value.
The assignment operator is given by default, along with the copy constructor, and default constructor. It assigns the value of each data member to its corresponding data member in the other object (i.e., shallow copy).
A std::vector? If so, std::vector implements the assignment operator by default. From the manpage:
"Assigns a copy of vector x as the new content for the vector object.
The elements contained in the vector object before the call are dropped, and replaced by copies of those in vector x, if any.
After a call to this member function, both the vector object and vector x will have the same size and compare equal to each other."
edit-one of these days I'm going to submit an answer first!
C++ provides a default copy constructor for you that is used for assignment, it copies the class member by member using their (also possibly default) copy constructors.

When reassigning variable, the destructor is not called.. (C++)

When a variable is reassigned, the destructor is not called:
Object foo = Object(a,b);
foo = Object(c,d);
so, the destructor will only be called at the end of the scope for Object(c,d), which can obviously cause problems.
Now, in this specific case it doesn't bother me too much: it is enough to declare 2 different objects:
Object foo1 = Object(a,b);
Object foo2 = Object(c,d);
In this way the destructor of both objects will be called at the end.
However, there is a case when I necessarily need to reassign a variable, i.e. in an object constructor such as:
SuperObject(Point point1, Point point2) : delay_object_(DelayObject(0)) {
double distance = distance(point1, point2);
double delay = distance / speed;
delay_object_ = DelayObject(delay);
}
In fact the DelayObject parameter is not easy to calculate (in this example I also omitted a few other passages), and I want to avoid doing it in the initialisation list.
I thought I can force the deletion by putting the object in the heap and explicitly calling the destructor:
SuperObject(Point point1, Point point2) : p_delay_object_(new DelayObject(0)) {
double distance = distance(point1, point2);
double delay = distance / speed;
delete p_delay_object_;
p_delay_object_ = new DelayObject(delay);
}
but this really looks ugly to me, as I prefer to use dynamic allocation only when strictly necessary. Am I missing something?
Cheers!
"the destructor will only be called at the end of the scope for Object(c,d)"
False. Object(c,d) is a temporary, and its destructor is called at the end of the full-expression which creates it. In this case, that's the semi-colon at the end of foo = Object(c,d);. The destructor of foo is called at end-of-scope.
The assignment operator of Object should free or re-use resources already held by foo, and copy resources held by the temporary. Not necessarily in that order (see copy-and-swap).
Edit: in response to comment.
Object foo = Object(a,b);
Either
A temporary is constructed using whatever two-argument constructor matches (a,b).
foo is constructed using the copy-constructor, passing the temporary as argument.
The temporary is destroyed.
Or
foo is constructed using whatever two-argument constructor matches (a,b).
The implementation is free to do either - this is permitted by "copy constructor elision".
foo = Object(c,d);
A temporary is constructed using whatever two-argument constructor matches (c,d).
The assignment operator for class Object is called on foo, passing the temporary as argument.
The temporary is destroyed.
Some time later, at the end of the scope, foo is destroyed.
In C++0x, move assignment would come into play if it exists for the class.
You should overload the assignment operator, which would, conceptually, copy construct the existing object and destroy the old 'this'.
class Object {
...
Object& operator= (const Object& other) {
if (this != &other) {
// copy 'other' into 'this'.
}
return *this;
}
...
};
then the foo = Object(c,d); line should do what you expect.
(Also as #Steve Jessop mentioned, the temporary object Object(c,d) will also be destructed after before the end of the scope.)
See What is The Rule of Three?.
Yes, you're forgetting that you can overload the assignment operator. The one provided by default by the compiler simply copies blindly all the fields of the objects, but you can provide your own that will do whatever you want, including disposing the resources of the object target of the assignment.
Notice that it's easy to get wrong an assignment operator (forgetting about corner cases, exception safety, ...), I advise you to read at least this part of our operator overloading FAQ, which in turn redirects to the explanation of the common copy and swap idiom, which is almost always the only sensible way to implement the assignment operator.
Edit
See in addition #Steve Jessop's answer, that considers another fundamental misunderstanding.
In all cases in which you write
SomeClass sc = SomeClass(parameters);
you are initializing a new object: you're creating a temporary (SomeClass(parameters)) and then initializing sc with a copy of it (via the copy constructor); this is both unnecessary and inefficient, the syntax to create an object on the stack in C++ is just
SomeClass sc(parameters);
Delegate calculation of DelayObject parameters to private (possibly static) methods and use them when constructing DelayObject in initializer list.