So I'm trying to write this class. One of the things I want to be able to do is to add two together, so I'm overloading the addition operator. But here's the thing, I don't want to return a pointer, I want to return the class "by value", so that the addition operator works without messing with pointers.
My current approach doesn't work, because the class I create goes out of scope, and the only other way I can think of is to do it with pointers. Is there any other way to do this, without calling new and allocating memory that will later have to be deleted by the user of the class?
The current code:
Polynomial operator+(const Polynomial &lhs, const Polynomial &rhs)
{
Polynomial newPoly;
newPoly.addWithOther(lhs);
newPoly.addWithOther(rhs);
return newPoly;
}
Well I figured it out. The copy constructor is called right after return is called. And the return register will take a copy of your object. Its here that any objects that are not returned will go out of scope. If you don't perform a deep copy of those objects, or in my case, a 'deep enough' copy, the members will be reallocated by the system.
Related
I've an operator and function which goal is to copy the values of the vector pointer to a vector. I've read that as long it's a vector pointer, deep copying methods would only copy its pointer, not its value. I'm wondering how to copy it's values over instead. (The vector is a member of CObject class)
Operator function:
void CObject::operator=(CObject& rhs)
{
this->ClearObject(); //Object will be cleared first
// How to perform the deep copy below?
copy(rhs.m_Vector.begin(), rhs.m_Vector.end(), back_inserter(this->m_Vector));
}
Declared as -> void operator=(CObject& rhs);
Example application of operator function (Performed in another class):
CObject* m_pObjectOne;
CObject m_ObjectTwo;
m_ObjectTwo = m_pObjectOne;
(Therefore, when m_pObjectOne is deleted in its class destructor, m_ObjectTwo loses its value)
Vector & others:
struct OBJECT_ITEM
{
char m_chType;
UINT m_nDataByte;
BYTE* m_pData;
CString m_strRecipeTag;
}
std::vector<OBJECT_ITEM> m_Vector;
I've also tried other deep copy methods like push_back() & assign() but it gives me the same result.
Any help would be appreciated!
Strive for the "rule of zero".
How to Deep Copy Values of Vector Pointer (Not just the pointer)?
Basically - don't. You should strive to follow the rule of zero: Unless otherwise necessary, set things up so that the default constructors, assignment operators and destructors do what they should.
In your case: Suppose you let CObject use its default (copy) assignment operator. That means, that rhs.m_Vector will be assigned to lhs.m_Vector. And vector assignment means that individual members of the vector are assigned to their corresponding members.
The way you wrote your vector, that won't do what you want: You wrote you want to avoid the case of "when m_pObjectOne is deleted in its class destructor, m_ObjectTwo loses its value)". Well, since you're willing to hold copies of the objects, consider something like the following:
struct OBJECT_ITEM
{
char m_chType;
UINT m_nDataByte;
MyContainer m_upData;
CString m_strRecipeTag;
}
And choose or write MyContainer to suit your needs. It could just be an std::vector<BYTE>; or if you don't want the size to change after construction, use a dynarray (not in the standard library these days; here's an alternative); etc. And your chosen container will actually get properly copied when you copy an OBJECT_ITEM. Finally, don't hold pointers to OBJECT_ITEM's - just hold actual OBJECT_ITEM's (which it seems you were already doing?)
And there, now you can no longer have dangling pointers - with no custom constructors, assignment operators or anything else like that.
can someone walk through exactly what happens with the memory in this operator overload function? I am confused on how exactly the object created inside the operator function gets deallocated in the main.
Object& operator+(const Object& other) {
Object o(*this); //create instance of o that deep copies first argument
...
//copy contents of other and add onto o
return o;
}
int main() {
Object b;
Object c;
Object a = b + c;
}
Edit: to be more specific, isn't it bad practice to create a local object in a function and then return it by reference? Wouldn't that cause a memory leak?
Edit 2: I am referencing my textbook Data abstraction & problem solving with c++ carrano which suggests an operator + overload for LinkedLists in this format: LinkedList<ItemType>& operator+(const LinkedList<ItemType>& rightHandSide) const;. They implemented the method in the way I described.
Edit 2.5: the full method pseudocode given by the book:
LinkedList<ItemType>& operator+(const LinkedList<ItemType>& rightHandSide) const {
concatList = a new, empty instance of LinkedList
concatList.itemCount = itemCount + rightHandSide.itemCount
leftChain = a copy of the chain of nodes in this list
rightChain = a copy of the chain of nodes in the list rightHandSide
concatList.headPtr = leftChain.headPtr
return concatList
}
Edit 3: Asked my professor about this. Will get to the bottom of this by tomorrow.
Edit 4: The book is wrong.
Returning a reference to a local object
As everyone else correctly states, returning a reference to a local object results in undefined behaviour. You will end up with a handle to a destroyed function-scope object.
Returning references in arithmetic operators
If you think about it, a+b should give you a result, but it shouldn't change a nor b. C++ however leaves it up to you to define how operators work on your own types so it's possible to implement the behaviour you need. This is why the operator+ usually has to create a new object and can't return a reference.
Compound assignments (+=, -=, etc) on the other hand do change the object itself so a += b is changing a. This is why it's usually being implemented by returning a reference (not to a local object, but to the instance itself):
Object& Object::operator+=(const Object& rhs)
{
// do internal arithmetics to add 'rhs' to this instance
return *this; // here we return the reference, but this isn't a local object!
}
It wouldn't cause a memory leak, but o gets destroyed when it goes out of scope, when the function returns. So the reference the caller has is junk. It might appear to work fine for a short time until the memory is overwritten later.
It is simply undefined behavior.
In terms of what happens to memory, the memory will not be reserved to the object after the function returns (because the object is now out of scope).
So it can contain ANYTHING, including the same object by way of coincidence.
Suppose that there's a class called Vector, I want to overload the assignment operator for it to make it able to work like this:
a = b = c;(a,b,v are objects of Vector class)
But one thing confused me.
Suppose that there are two prototypes:
Vector & operator=(const Vector & v);
const Vector & operator=(const Vector & v);
Both two work in the case of 'a=b=c'.
So, which one is better or right?
For starters, naming your class "Vector" will probably result in frequent confusion and mixups, with std::vector. You should pick a better name. Unfortunately, "array" is also now taken...
The first one is the standard assignment operator. The assignment operator is only defined, of course, for mutable class instances, so it should return a reference to a mutable class instance.
Interesting, personally I would go with the first one, the reason for that is that the second one, is forcing constness on the result. Which might be something you don't want, also you can enforce constness externally if you want, by returning from outer functions with const etc.
At least you might be able to manually modify vector components manually.
I've been reading a lot that if you need an assignment operator then do not use reference member variables. I understand that you can not re-assign a reference but could you not get around this by just re-assigning all the data within that reference variable in your assignment operator since you cannot re-assign the reference itself?
Something like this:
class MyClass {
AnotherClass& someObject;
...
public:
...
MyClass& operator= (const MyClass& that) {
if (&that != this) {
this.someObject.member1 = that.someObject.member1;
this.someObject.member2 = that.someObject.member2;
}
return *this;
}
}
Is there a problem with this or could problems arise by attempting to do assignment this way?
Yes, you could run into problems. Say you have two MyClass instances, A and B, which share the same AnotherClass object. If you assign A a different value, then you'll muck up B's member.
What is this variable used for?
If many MyClasses need to share and modify the same AnotherClass, then use AnotherClass *. Then just redirect your pointer upon assignment. You'd have to keep track of how many MyClasses own the AnotherClass though, so either keep track of that in AnotherClass, or use some kind of "smart" pointer.
If AnotherClass is too large to store many copies of, or there's many, many instances of MyClass, then a const AnotherClass * would work better. Again, you'll have to keep track of how many pointers to it exist, so you don't leak memory.
If it's small, there are few MyClasses, and there's no need to share it between them: use normal objects. The performance impact will probably be negligible.
When overloading the = operator, should one make the contents of one object equal to the contents of the other object OR do you make the pointer of the object point to the same object?
Reading back on the question it seems that the contents should be copied and not the pointers. But I just can't figure it out, So I would be grateful if someone would explain what I should do, I know how to do both, I'm just not sure which one to choose.
class IntObject
{
private:
int *pi_One;
public:
IntObject(void);
IntObject::IntObject(int const &i_one);
~IntObject(void);
IntObject & operator=(const IntObject&);
};
IntObject::IntObject()
{
pi_One = new int(0);
}
IntObject::IntObject(int const &i_one)
{
pi_One = new int(i_one);
}
IntObject::~IntObject(void)
{
delete pi_One;
}
IntObject & IntObject::operator=(const IntObject& c) {
//This copies the pointer to the ints
this->pi_One = c.pi_One;
return *this;
}
It depends on what semantics you want to have in your type. If you want value semantics, then copy the contents (deep copy, as is the case in std::vector), if you want reference semantics (shallow copy, as in std::shared_ptr)
You should definitely copy the contents, not the pointers. Think about what you will do when one of the objects which both hold the same pointer is destroyed; you can't delete the pointer because the other object would be affected as well, but you can't not delete it either because you'd cause memory leaks. You'd have to use reference counting and everything would get a whole lot more complicated.
The contents should be copied (in fact, changing the pointer of the object shouldn't actually be possible - I can't imagine how you would do that - and even if it is somehow, you're not supposed to do it). You also have to take care of the differences between deep and shallow copies, especially if your class contains pointers (or containers with pointers in them).
Now that I think about it, I'm not even sure which pointer you could possibly want to reassign. Unless you are already working with a pointer - those already have an '=' operator that shouldn't be overloaded though.
The principle of least astonishment would say to copy the content. When using operator= on any other object, you wouldn't expect it to copy pointers.
If you keep your destructor as it is, then you should change assignment overload. It would be also wise that nobody is attempting assigning IntObject to itself:
IntObject & IntObject::operator=(const IntObject& c) {
if (this != &c)
{
//This copies the pointer to the ints
*this->pi_One = *c.pi_One;
}
return *this;
}
Otherwise, there will be attempt to free freed memory in IntObject's destructor