Unit now I've never needed to overload the assignment parameter or write a Copy Constructor
(at least, it seems I never had to, because I never had problems)
as far as I know the Assignment Operator must be overloaded when I want to copy a Object and its values to another Object after initialization (Same of CopyConstructor, but when its initialized).
Object a;
Object b;
// do something with a
b = a; //for this line, the Assignment Parameter must be overloaded (nearly never do such things)
Object c = a; // needs a Copy constructor
But If I would write it like this:
Object a;
Object* b;
b = &a; //I think I won't need one here since b actually points to Object a
Object* c = a; // I think same here
But what should I do, if I copy a object outside of its own class/parent class.
class MyOtherClass{Object obj..........}
void MyOtherClass::SetObject(Object obj)
{
this->obj = obj; // Assignment operator overloading needed in class Object?
}
do I have to overload the Assignment Operator in the Object class?
What if I do following:
void MyOtherClass::SetObject(Object &obj)
{
this->obj = obj; // Assignment operator overloading needed in class Object?
}
And the final question, does this also include Enums?(I think yes)
void MyOtherClass::SetObject(ENumClass Eobj)
.
.
For the question of whether or not to implement an assignment operator, the answer is - it depends.
Remember that the compiler will generate its own default assignment operator if you do not provide one yourself (and in C++11, if you do not explicitly disable the default operator). The default operator performs an assignment of each individual class member using their own assignment operators.
So as long as your class members are assignment-safe in their own right, then the default operator is sufficient and you do not need to provide your own operator. You only need to provide your own operator when you need to perform custom actions, like deep-copying dynamically allocated members, debug logging, input validation, etc.
Why do you use a separate method SetObject() which duplicates operator=() semantic?
So that correctly assign a base class to derived you can overload operator=() in the derived object this way
DerivedObj& DerivedObj::operator=(const BaseObj& rhs){
// call parent operator= in functional form
BaseObj::operator=(rhs);
return *this;
}
Of course you should implement
BaseObj& BaseObj::operator=(const BaseObj& rhs)
However if you need assign base class to derived I would not say it's a good design
It is legal to write an assignment operator that assigns from a base type and it is also legal to write an assignment operator that assigns from a concrete object of the same type. However, even though both are legal, it is generally better design to implement assignment from an object of the same type or from other concrete types for which such an assignment actually makes sense and not from a general type.
That being said, it does vary from application to application. To be a little more specific, consider:
Shape
/ | \
Triangle Quadrilateral Circle
... it probably would not make sense to have an assignment operator in Circle that could assign from any Shape. What would that method even do? These different implementations have nothing in common.
Now, alternatively, consider:
Point2D
/ \
CartesianCoord PolarCoord
... in an application like this, it might make sense to provide an assignment operator that accepts a general Point2D in order to facilitate conversions between the two types. In this case, all implementations represent the same information and can be converted non-destructively between representations. As a result, allowing a more general conversion would make sense in this context.
So, really, it's all about what makes sense conceptually. If you can assign to/from an object in a way that does not destroy information, it is sane; if your assignment is destructive, it's likely a poor design.
As for the parameters, one typically uses "const T&" (where "T" is the type from which you are assigning) or "T&&" in the case of destructive assignment. The return type of the assignment should be a reference to an object of the same type as the current object. In other words:
class CartesianCoord : public Point2D {
public:
// ...
CartesianCoord& operator=(const Point2D&);
};
Or
class CartesianCoord : public Point2D {
public:
// ...
CartesianCoord& operator=(const Point2D&);
CartesianCoord& operator=(CartesianCoord&&); // fast destructive assignment
};
Or
class CartesianCoord : public Point2D {
public:
// ...
CartesianCoord& operator=(const CartesianCoord&); // if conversion disallowed
CartesianCoord& operator=(CartesianCoord&&); // fast destructive assignment
};
Related
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
I'm struggling to basically understand how the assignment operator works, or perhaps I haven't defined the right one, or I've come upon some C++ gotcha; not sure.
I have a class like this:
class A
{
public:
A();
A(const A &rhs);
//some other ctors
//and functions here
A& operator=(A rhs);
A create_half();
double* m_data;
};
Here is the body of create_half; it appears to be relevant to the situation
A A::create_half(){
//construct a new A
A mya;
//do stuff to mya here,
//and then return the new A
return mya;
}
Here is the copy constructor, at least a shortened version of it. This is the code that is skipped due to standard -- at least if this is what's truly going on.
A::A(const A& rhs):
m_data(new double[1])
{
*m_data = *(rhs.m_data);
//or something similar, essentially
//a deep copy
}
Then in the code I try to write something like this
A a_instance;
//do stuff to a_instance
//this doesn't call any = operator or
//copy c-tor I try to define, why?
A b_instance = A.create_half();
//but this works fine
//the = operator I have def'd is called
A b_instance;
b_instance = A.create_half();
The line that doesn't work as I want it to seems to do a default copy (ie, b_instance.m_data is set to a_instance.m_data) even though neither my copy c-tor now my assignment operator contain this operation.
For the problematic line, I'm not able to step into the assignment operator; that's why I think I have the wrong signature, or something similar.
Any ideas?
EDIT: Sorry for misleading you guys -- no class B exists.
EDIT AGAIN: I've accepted an answer, and I've added some detail to the snippets above to try to elucidate what is really going on.
Since the instance of A created by create_half() isn't bound to a reference, the standard allows elision of the copy constructor, which, critically, allocates new memory for b_instance, and does the deep copy.
That seems pretty bold, to me! I don't think I'll see an answer, since this edit is sometime after the initial posting, but what would be a better design pattern here?
This
A a_instance();
is a function declaration that has no parameters and has return type A.
This statement
B b_instance = A.create_half();
syntactically is invalid. At least it should be written as
B b_instance = A().create_half();
In this statement an object of type B is created from an object of type A. I can say nothing whether this statement is correct because you did not show the class B definition.
This statement is also invalid
b_instance = A.create_half();
There must be
b_instance = A().create_half();
There is used indeed an assignment operator (maybe even the copy assignment operator provided that class B has a conversion constructor or class A has a conversion function) but for class B. You did not show how you defined class B. So again I can say nothing what is wrong with this assignment operator.
As for the signature of the copy assignment operator of class A
A& operator=(A rhs);
then it is valid though it would be better if you declared it as
A& operator=( const A &rhs );
EDIT: As you changed your original post then I need to append my message relative to your question in the following code snippet
//this doesn't call any = operator or
//copy c-tor I try to define, why?
A b_instance = A.create_half();
According to the C++ Standard
31 When certain criteria are met, an implementation is allowed to omit
the copy/move construction of a class object, even if the constructor
selected for the copy/move operation and/or the destructor for the
object have side effects. In such cases, the implementation treats the
source and target of the omitted copy/move operation as simply two
different ways of referring to the same object, and the destruction of
that object occurs at the later of the times when the two objects
would have been destroyed without the optimization.
One of the "certin criteria" is
— when a temporary class object that has not been bound to a reference
(12.2) would be copied/moved to a class object with the same
cv-unqualified type, the copy/move operation can be omitted by
constructing the temporary object directly into the target of the
omitted copy/move
I have a class Step derived from std::vector<unsigned int>. I need to overload assignment operator because of the deep copy used in assignment of a value returned from a static method. I can't figur out how should I copy all elements of rhv to this in assignment:
class Step : public std::vector<unsigned int>
{
public:
friend std::ostream& operator<<(std::ostream& outStream, const Step& step);
Step& operator =(const Step& rhv);
static Step fromString(const std::string &input);
// Something like: Step x = Step::fromString("12 13 14 15 16");
private:
double time;
double pause;
unsigned int id;
std::string name;
};
and then overloading =:
Step& Step::operator =(const Step& rhv)
{
time = rhv.time;
pause = rhv.pause;
id = rhv.id;
// How should I copy contents of rhv to `this` safely?
return *this;
}
I'm not 100% sure from your question, but I think you are asking about calling the parent operator=. In that case you have two options:
std::vector<unsigned int>::operator=(rhv); //either explicitly call the parent assignment op
*static_cast<std::vector<unsigned int>*>(this) = rhv; //or cast this to parentclass and call assignment on that
Of course in the code you have shown us you don't do any manual resource handling, so I don't see why you want to write your own assignment operator, the compiler generated one should do fine. Besides if you write your own assignment operator you might want to head the rule of three and write your own copy constructor and destructor too (at least in C++03, C++11 can be a bit different due to movable but not copyable classes).
As another sidenote: Most standardlibrary classes are not designed to be derived from, so you might want to rethink your design requiering you to inherit form std::vector
Inheriting from standard containers is generally considered a bad idea because they aren't designed to be used as base classes (no virtual destructor among other things). Composition is preferred in pretty much every case.
Assuming you've decided to step into this minefield, you can invoke the parent assignment operator with a static_cast.
*static_cast<std::vector<unsigned int>*>(this) = rhv;
and don't forget to assign name as well.
In this case you really don't have to overload operator= because the default generated one will work just fine (by assigning each member and base class in turn).
If you define your own operator, you can call the base class operator, just like you would call another base class function
std::vector<unsigned int>::operator=(rhv);
and let the vector handle its own assignment.
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.
Consider a class of which copies need to be made. The vast majority of the data elements in the copy must strictly reflect the original, however there are select few elements whose state is not to be preserved and need to be reinitialized.
Is it bad form to call a default assignment operator from the copy constructor?
The default assignment operator will behave well with Plain Old Data( int,double,char,short) as well user defined classes per their assignment operators. Pointers would need to be treated separately.
One drawback is that this method renders the assignment operator crippled since the extra reinitialization is not performed. It is also not possible to disable the use of the assignment operator thus opening up the option of the user to create a broken class by using the incomplete default assignment operator A obj1,obj2; obj2=obj1; /* Could result is an incorrectly initialized obj2 */ .
It would be good to relax the requirement that to a(orig.a),b(orig.b)... in addition to a(0),b(0) ... must be written. Needing to write all of the initialization twice creates two places for errors and if new variables (say double x,y,z) were to be added to the class, initialization code would need to correctly added in at least 2 places instead of 1.
Is there a better way?
Is there be a better way in C++0x?
class A {
public:
A(): a(0),b(0),c(0),d(0)
A(const A & orig){
*this = orig; /* <----- is this "bad"? */
c = int();
}
public:
int a,b,c,d;
};
A X;
X.a = 123;
X.b = 456;
X.c = 789;
X.d = 987;
A Y(X);
printf("X: %d %d %d %d\n",X.a,X.b,X.c,X.d);
printf("Y: %d %d %d %d\n",Y.a,Y.b,Y.c,Y.d);
Output:
X: 123 456 789 987
Y: 123 456 0 987
Alternative Copy Constructor:
A(const A & orig):a(orig.a),b(orig.b),c(0),d(orig.d){} /* <-- is this "better"? */
As brone points out, you're better off implementing assignment in terms of copy construction. I prefer an alternative idiom to his:
T& T::operator=(T t) {
swap(*this, t);
return *this;
}
It's a bit shorter, and can take advantage of some esoteric language features to improve performance. Like any good piece of C++ code, it also has some subtleties to watch for.
First, the t parameter is intentionally passed by value, so that the copy constructor will be called (most of the time) and we can modify is to our heart's content without affecting the original value. Using const T& would fail to compile, and T& would trigger some surprising behaviour by modifying the assigned-from value.
This technique also requires swap to be specialized for the type in a way that doesn't use the type's assignment operator (as std::swap does), or it will cause an infinite recursion. Be careful of any stray using std::swap or using namespace std, as they will pull std::swap into scope and cause problems if you didn't specialize swap for T. Overload resolution and ADL will ensure the correct version of swap is used if you have defined it.
There are a couple of ways to define swap for a type. The first method uses a swap member function to do the actual work and has a swap specialization that delegates to it, like so:
class T {
public:
// ....
void swap(T&) { ... }
};
void swap(T& a, T& b) { a.swap(b); }
This is pretty common in the standard library; std::vector, for example, has swapping implemented this way. If you have a swap member function you can just call it directly from the assignment operator and avoid any issues with function lookup.
Another way is to declare swap as a friend function and have it do all of the work:
class T {
// ....
friend void swap(T& a, T& b);
};
void swap(T& a, T& b) { ... }
I prefer the second one, as swap() usually isn't an integral part of the class' interface; it seems more appropriate as a free function. It's a matter of taste, however.
Having an optimized swap for a type is a common method of achieving some of the benefits of rvalue references in C++0x, so it's a good idea in general if the class can take advantage of it and you really need the performance.
With your version of the copy constructor the members are first default-constructed and then assigned.
With integral types this doesn't matter, but if you had non-trivial members like std::strings this is unneccessary overhead.
Thus, yes, in general your alternative copy constructor is better, but if you only have integral types as members it doesn't really matter.
Essentially, what you are saying is that you have some members of your class which don't contribute to the identity of the class. As it currently stands you have this expressed by using the assignment operator to copy class members and then resetting those members which shouldn't be copied. This leaves you with an assignment operator that is inconsistent with the copy constructor.
Much better would be to use the copy and swap idiom, and express which members shouldn't be copied in the copy constructor. You still have one place where the "don't copy this member" behaviour is expressed, but now your assignment operator and copy constructor are consistent.
class A
{
public:
A() : a(), b(), c(), d() {}
A(const A& other)
: a(other.a)
, b(other.b)
, c() // c isn't copied!
, d(other.d)
A& operator=(const A& other)
{
A tmp(other); // doesn't copy other.c
swap(tmp);
return *this;
}
void Swap(A& other)
{
using std::swap;
swap(a, other.a);
swap(b, other.b);
swap(c, other.c); // see note
swap(d, other.d);
}
private:
// ...
};
Note: in the swap member function, I have swapped the c member. For the purposes of use in the assignment operator this preserves the behaviour to match that of the copy constructor: it re-initializes the c member. If you leave the swap function public, or provide access to it through a swap free function you should make sure that this behaviour is suitable for other uses of swap.
Personally I think the broken assignment operator is killer. I always say that people should read the documentation and not do anything it tells them not to, but even so it's just too easy to write an assignment without thinking about it, or use a template which requires the type to be assignable. There's a reason for the noncopyable idiom: if operator= isn't going to work, it's just too dangerous to leave it accessible.
If I remember rightly, C++0x will let you do this:
private:
A &operator=(const A &) = default;
Then at least it's only the class itself which can use the broken default assignment operator, and you'd hope that in this restricted context it's easier to be careful.
I would call it bad form, not because you double-assign all your objects, but because in my experience it's often bad form to rely on the default copy constructor / assignment operator for a specific set of functionality. Since these are not in the source anywhere, it's hard to tell that the behavior you want depends on their behavior. For instance, what if someone in a year wants to add a vector of strings to your class? You no longer have the plain old datatypes, and it would be very hard for a maintainer to know that they were breaking things.
I think that, nice as DRY is, creating subtle un-specified requirements is much worse from a maintenance point of view. Even repeating yourself, as bad as that is, is less evil.
I think the better way is not to implement a copy constructor if the behaviour is trivial (in your case it appears to be broken: at least assignment and copying should have similar semantics but your code suggests this won't be so - but then I suppose it is a contrived example). Code that is generated for you cannot be wrong.
If you need to implement those methods, most likely the class could do with a fast swap method and thus be able to reuse the copy constructor to implement the assignment operator.
If you for some reason need to provide a default shallow copy constructor, then C++0X has
X(const X&) = default;
But I don't think there is an idiom for weird semantics. In this case using assignment instead of initialization is cheap (since leaving ints uninitialized doesn't cost anything), so you might just as well do it like this.