C++ overloading assignment operator - c++

I have a class called Location and I needed to add a CArray to its member variables. This change caused the need to overload the assignment operator.
Is there a way to copy all of the variables in this class type that were being copied before I made the change and just add the additional code to copy the CArray without copying every single member variable individually?
Location& Location::operator=(const Location &rhs)
{
// Only do assignment if RHS is a different object from this.
if (this != &rhs)
{
//Copy CArray
m_LocationsToSkip.Copy(rhs.m_LocationsToSkip);
//Copy rest of member variables
//I'd prefer not to do the following
var1 = rhs.var1;
var2 = rhs.var2;
//etc
}
return *this;
}

Yes, sort of. Use a type that overloads operator= itself, so you don't have to do it in the containing class instead. Even when writing MFC code, I still mostly use std::vector, std::string, etc., instead of the MFC collection and string classes. Sometimes you're pretty much stuck using CString, but I can't recall the last time I used CArray instead of std::vector.

Yes. What I usually do is to put everything in a Members struct in the class except what is not copyable. Like this:
class Location
{
struct Members
{
int var1, var2;
};
Members m;
CArray m_LocationsToSkip;
public:
Location& operator=(Location const& rhs);
};
Location& Location::operator=(const Location &rhs)
{
// Only do assignment if RHS is a different object from this.
if (this != &rhs)
{
//Copy CArray
m_LocationsToSkip.Copy(rhs.m_LocationsToSkip);
//Copy rest of member variables
m = rhs.m; //will use Members automatically generated operator=
//which should do the correct thing because you only put
//normally copyable members in m
}
return *this;
}
I first posted about this here: https://stackoverflow.com/questions/469696/what-is-your-most-useful-c-c-utility/1609496#1609496

No you cant.
Best way to do this is use script to generate real code.

This is usually done with what's called "copy and swap idiom". You implement a copy constructor and a swap() method that exchanges member values and, most importantly, pointers to external data. With that your assignment operator looks like:
C& C::operator=( const C& c ) {
C tmp( c );
this->swap( tmp );
return *this;
}
You don't even need a self-assignment guard with this.

Related

Assignment operator when there are static, const members?

I have to write one new class with members something like
class A
{
static int i;
const int j;
char * str;
...
...
};
Now I want to write assignment operator for it.
A& A::operator=(const A& rhs)
{
if(this != rhs)
{
delete [] str;
str = new char[strlen(rhs.str)+1];
strcpy(str, rhs.str);
}
return * this;
}
Is it right? I shall ignore the static and const members(?).
The assignment operator copies one object into another. Since all objects of the same type share the same static members, there's no reason to copy the static members.
const members are another matter. You can't (well, shouldn't) change them, but if two objects have different values for a const member, it might not be a good idea to copy one object into another; the const member won't have the right value. That's why the compiler doesn't generate a copy assignment operator for classes that have const members. So you first have to be sure that copying such an object makes sense, even with the wrong value for the const members; and then ask yourself why it has const members if they don't affect how it behaves.
References too. (yes, there's an echo in here)
Static members don't belong to a single object, so you don't need to copy those.
const members can't be changed, so you really can't do a proper copy. References too.

Add one object to another set of objects in C++

I'm working on my assignment in C++ course.
I have to create operator+= which will add an object to another set of object.
So, how do I implement operator+= here?
class classNew
{
anotherClass *my_objects;
public:
// TODO: classNew(int, char const *)
classNew operator+=(const anotherClass & rhs);
};
int main()
{
classNew d1(7, "w");
anotherClass sgs[5];
// somehow init sgs[0]..[4]?
for (int i=0; i<sizeof(sgs)/sizeof(*sgs); ++i)
d1 += sgs[i];
}
UPDATE:
I have something like this
newClass newClass::operator+=(const anotherClass& seg){
this->my_objs[n_seg] = seg;
return *this;
}
Unless your operator+= is intended to modify the object you're adding, which would be highly unusual, I'd suggest one two simple changes to the signature:
classNew & classNew::operator+=(const anotherClass& rhs);
You always want to return a reference to the class, otherwise you get a copy.
You have a pointer to anotherClass in your class, I assume that this is actually a pointer to an array. You simply have to copy the passed rhs to the appropriate spot in your array, reallocating it and growing it if necessary. If my assumption is incorrect, you just need to do whatever addition is defined as for your class.
If this weren't an assignment I would also suggest replacing the pointer with a std::vector<anotherClass>.

Making shallow copy inside assignment operator

I need to implement an assignment operator for a class with a lot of members which I don't want to assign manually. Can I first make a shallow memory copy and then perform the necessary initializations?
class C
{
public:
C &operator=(const C &rhs)
{
if (&rhs == this)
return *this;
memcpy(this, &rhs, sizeof(C));
Init(rhs);
return *this;
}
.........
};
Thanks.
No. Unless the object has a POD type, this is undefined behavior. And
a user defined assignment operator means that it's not a POD. And in
practice, it could fail for a number of reasons.
One possible solution is to define a nested POD type with the data
members, and simply assign it, e.g.:
class C
{
struct Data { /* ... */ };
Data myData;
public:
C& operator=( C const& other )
{
myData = other.myData;
return *this;
}
};
Of course, that means that you need to constantly refer to each member
as myData.x, rather than simply x.
Well you could, but all your copied pointer members(if any) will then point to the same object and if that object goes out of scope, You would be left with a dangling pointer for all other objects which refer to it.
You are trying to dereference a C++ reference using the * operator. Unless you have operator* defined for this class it's not gonna work.
I mean in line
memcpy(this, *rhs, sizeof(C));

Implement a copy constructor for the erase function of vector

Based on issues growing out of previous questions: vector::erase with pointer member, Remove elements of a vector inside the loop, I still need some help on vector.erase function. I was indicated to implement a copy constructor to make the erase function work on a vector, something that is also mentioned in another question. It is essential to implement a function operator in my relevant class. On doing this I get another error on creating the copy constructor and I cannot find the reason for long. The error is “Player::Player(const Player& otherPlayer) does not provide an initiallizer for:” . What am I doing wrong? Take into consideration that Player contains as class members map, pointers and a reference (bank is a reference) . Is a simple assignment adequate for the initialization?
What should I do?
class Player
{
public:
Player(int,int,string, Bank&);
Player(const Player&);
Player& operator = (const Player& rhs);
Player::Player(const Player& otherPlayer)
{
ID = otherPlayer.ID;
pName = otherPlayer.pName;
pMoney = otherPlayer.pMoney;
doubleIndicator = otherPlayer.doubleIndicator;
position = otherPlayer.position;
bank = otherPlayer.bank;
colBought = otherPlayer.colBought;
housesColBuilt = otherPlayer.housesColBuilt;
}
Update:
I get a warning at the point of implementantion of the operator= as:"returning address of a local variable or temporary". Does this evoke a real problem? If so, how could I modify it to get over this?
Player& Player::operator=(const Player& rhs)
{
return Player(rhs);
}
In this way, I still receive a warning that the recursive function will cause stack overflow:
Player& Player::operator=(const Player& rhs)
{
*this = Player(rhs);
return *this;
}
Any hint?
You must initialize references that are members of a class with a member initializer in the constructor:
Player::Player(const Player& otherPlayer) :
bank(otherPlayer.bank)
{
//...
}
This is needed because otherwise the reference would be uninitialized, which is not allowed.
Note that the assignment bank = otherPlayer.bank; does something different: It assigns the object that is referenced, rather than sets the reference itself.
It's also good style to initialize other members (even if they aren't references) in the same way, as it can lead to more optimal code (otherwise members could be default-constructed before being assigned).

Implement copy-ctor in terms of copy-operator or separately?

This is not a duplicate of Implementing the copy constructor in terms of operator= but is a more specific question. (Or so I like to think.)
Intro
Given a (hypothetical) class like this:
struct FooBar {
long id;
double valX;
double valZ;
long valN;
bool flag;
NonCopyable implementation_detail; // cannot and must not be copied
// ...
};
we cannot copy this by the default generated functions, because you can neither copy construct nor copy a NonCopyable object. However, this part of the object is an implementation detail we are actually not interested in copying.
It does also does not make any sense to write a swap function for this, because the swap function could just replicate what std::swap does (minus the NonCopyable).
So if we want to copy these objects, we are left with implementing the copy-ctor and copy-operator ourselves. This is trivially done by just assigning the other members.
Question
If we need to implement copy ctor and operator, should we implement the copy ctor in terms of the copy operator, or should we "duplicate" the code with initialization list?
That is, given:
FooBar& operator=(FooBar const& rhs) {
// no self assignment check necessary
id = rhs.id;
valX = rhs.valX;
valZ = rhs.valZ;
valN = rhs.valN;
flag = rhs.flag;
// don't copy implementation_detail
return *this;
}
Should we write a)
FooBar(FooBar const& rhs) {
*this = rhs;
}
or b)
FooBar(FooBar const& rhs)
: id(rhs.id)
, valX(rhs.valX)
, valZ(rhs.valZ)
, valN(rhs.valN)
, flag(rhs.flag)
// don't copy implementation_detail
{ }
Possible aspects for an answer would be performance vs. maintainability vs. readability.
Normally you implement assignment operator in terms of copy constructor (#Roger Pate's version):
FooBar& operator=(FooBar copy) { swap(*this, copy); return *this; }
friend void swap(FooBar &a, FooBar &b) {/*...*/}
This requires providing a swap function which swaps relevant members (all except implementation_detail in your case).
If swap doesn't throw this approach guarantees that object is not left in some inconsistent state (with only part members assigned).
However in your case since neither copy constructor, nor assignment operator can throw implementing copy constructor in terms of assignment operator (a) is also fine and is more maintainable then having almost identical code in both places (b).
In general, I prefer b) over a) as it explicitly avoids any default construction of members. For ints, doubles etc. that isn't a consideration, but it can be for members with expensive operations or side effects. It's more maintainable if you don't have to consider this potential cost/issue as you're adding and removing members. Initialiser lists also support references and non-default-constructable elements.
Alternatively, you could have a sub-structure for the non-"implementation detail" members and let the compiler generate copying code, along the lines:
struct X
{
struct I
{
int x_;
int y_;
} i_;
int z_;
X() { }
X(const X& rhs)
: i_(rhs.i_), z_(0) // implementation not copied
{ }
X& operator=(const X& rhs)
{
i_ = rhs.i_;
return *this;
}
};
If you're really bothered about replicating std::swap, why not put everything other than the implementation detail into a struct?
struct FooBarCore {
long id;
double valX;
double valZ;
long valN;
bool flag;
// ...
};
struct FooBar {
FooBarCore core_;
NonCopyable implementation_detail; // cannot and must not be copied
};
then you can use std::swap for this struct in your copy function for FooBar.
FooBar& operator=(const FooBar &src) {
FooBarCore temp(src.core_)
swap(temp,*this.core_);
return *this;
}
Okay, another try, based on my comment to this answer.
Wrap the implementation_detail in a copyable class:
class ImplementationDetail
{
public:
ImplementationDetail() {}
ImplementationDetail(const ImplementationDetail&) {}
ImplementationDetail& operator=(const ImplementationDetail&) {}
public: // To make the example short
Uncopyable implementation_detail;
};
and use this class in your FooBar. The default generated Copy Constructor and Copy Assignment Operator for Foobar will work correctly.
Maybe it could even derive from Uncopyable so you don't get implementation_detail.implementation_detail all over your code. Or if you control the code to the implementation_detail class, just add the empty Copy Constructor and empty Assignment Operator.
If the Copy Constructor does not need to copy implementation_detail and still will be correct (I doubt the latter, but let's assume it for the moment), the implementation_detail is superfluous.
So the solution seems to be: make the implementation_detail static and rely on the default generated Copy Constructor and Assignment Operator.