|
||||||||||||||||||
Add Forum to Favorites | Send Topic To a Friend | View Forum FAQ | Track this topic |
Last Thread Next Thread ![]() |
| operator+ overloading problem |
|
![]() danbis_uk Member since: 7/21/2004 From: United Kingdom |
||||
|
|
||||
| I am having problems trying to figure out how to get my operator+ to work. I believe the problem is down to the fact that p is a pointer, but i cant for the life of me figure out how to solve it. I would be very grateful if someone would point me in the right direction. (as soon as i add (temp = a) to my + operator, my Point array messes up.) class Obstacle{ Point *p; int n; public: Obstacle(); Obstacle(int); ~Obstacle(); Obstacle &operator+= (const Obstacle&); Obstacle &operator= (const Obstacle&); Obstacle &operator+ (Obstacle); }; Obstacle &Obstacle::operator+= (const Obstacle &a) { Point *temp = new Point[n]; for (int i = 0; i < n; i++) temp[i] = p[i]; if (p != NULL) delete[] p; p = new Point[n + a.n]; for(int i = 0; i < n; i++) p[i] = temp[i]; for(int i = 0; i < a.n; i++)p[n+i] = a.p[i]; n+=a.n; if (temp != NULL) delete[] temp; return *this; } // overloaded = operator Obstacle &Obstacle::operator= (const Obstacle &a) { if(this != &a){ if (p != NULL) delete[]p; p = new Point[a.n]; for (int i = 0; i < a.n; i++)p[i] = a.p[i]; n = a.n; } return *this; } Obstacle &Obstacle::operator+ (Obstacle a) { Obstacle temp = Obstacle(); temp = a; return temp; } Thanks, Dan |
||||
|
||||
![]() Kippesoep Member since: 10/25/2001 From: Etten, Netherlands |
||||
|
|
||||
| This is probably caused by invalid values for p. You don't show the default constuctor, but I would guess that it doesn't initialise p (and n) to 0. Add something like Obstacle () : p (0), n (0) {} to your class declaration and it should work. Also, in your operator + you're returning a reference to a temporary object, which is A Bad Thing. Make it look something like this: Obstacle Obstacle::operator+ (const Obstacle &a) { Obstacle temp = *this; temp += a; return temp; } Finally, note that checking for NULL is not necessary when deleting. Save yourself a lot of typing and just use "delete [] p". Kippesoep |
||||
|
||||
![]() Jingo Member since: 11/2/2003 From: Bath, United Kingdom |
||||
|
|
||||
There isn't usually a reason to make operator+ a member functionObstacle operator+(Obstacle copy_ob_1, const Obstacle& ob_2){ copy_ob_1 += ob_2; return copy_ob_1; } Doing it like this gives you a better abstraction, and prevents the pollution of the inclass public interface, and also ensures that operator+= and operator+ behave consistently. |
||||
|
||||
![]() snk_kid Member since: 5/22/2003 From: United Kingdom |
||||
|
|
||||
Quote: Thats a little strange why are you passing one parameter by value and the other by reference? by doing that you end making extra copies, this is preferable:
class A {
public:
A& operator+=(const A&) {
//....
return *this;
}
};
inline A operator+(const A& a, const A& b) {
return (A(a) += b);
}
|
||||
|
||||
![]() Jingo Member since: 11/2/2003 From: Bath, United Kingdom |
||||
|
|
||||
| operator+ has to create a copy somewhere, otherwise it would be no different to operator+=, creating a copy in the parameter seems like as good a place as any to create it. |
||||
|
||||
![]() snk_kid Member since: 5/22/2003 From: United Kingdom |
||||
|
|
||||
Quote: But if any of the data members are pointers (as in the above example) and you've defined a proper copy constructor & assignemt operators you'll end up making 2 deep-copies with that method, once for the paramter pass, and then for using "+=" in your example. |
||||
|
||||
![]() Jingo Member since: 11/2/2003 From: Bath, United Kingdom |
||||
|
|
||||
| Your method also creates 2 copies though, just in a different place. Both create 2 copies in 2003.net, both methods create 3 copies in vc++6. |
||||
|
||||
![]() snk_kid Member since: 5/22/2003 From: United Kingdom |
||||
|
|
||||
Quote: Sorry i was meant to say 3 copies not 2, third being on return if it isn't optimized, where as the one i posted will 2 and may even be one if optimized. |
||||
|
||||
![]() Jingo Member since: 11/2/2003 From: Bath, United Kingdom |
||||
|
|
||||
| Well they could both be implemented with one copy if the return value optimization is used. The only difference between the 2 methods is that I used the named variable created in the passing of the parameter, and you use the unnamed variable created in the += expression, both can be opitmized away. |
||||
|
||||
![]() Direct4D Member since: 11/27/2003 From: The Netherlands |
||||
|
|
||||
Quote: Only i would make that operator+ return by const value, like this: inline const A operator+(A a, const A& b) { return (a += b); } Reason: Quote: |
||||
|
||||
![]() danbis_uk Member since: 7/21/2004 From: United Kingdom |
||||
|
|
||||
| thanks for all the help. I sort of managed to get it working. It returns the right values, but i get a debug assertion failure when my program finishes. I must have a memory leak somewhere. adding inline onto the operator+ function enabled me to recieve the right point values but also seems to cause the error. You can now see the reason that i check for NULL before deleting. It is probably a little pointless setting the pointer to be NULL in the constructor though class Obstacle{ Point *p; int n; public: Obstacle(); ~Obstacle(); const Obstacle &operator+= (const Obstacle&); const Obstacle &operator= (const Obstacle&); void addPoint(int, int); }; // Implementation //////////////////////////////////////// // Constructor Obstacle::Obstacle() { p = NULL; n = 0; } // Destructor Obstacle::~Obstacle() { if (p != NULL) delete[] p; } // overloaded += operator const Obstacle &Obstacle::operator+= (const Obstacle &a) { Point *temp = new Point[n]; for (int i = 0; i < n; i++) temp[i] = p[i]; if (p != NULL) delete[] p; p = new Point[n + a.n]; for(int i = 0; i < n; i++) p[i] = temp[i]; for(int i = 0; i < a.n; i++)p[n+i] = a.p[i]; n+=a.n; delete[] temp; return *this; } // overloaded = operator const Obstacle &Obstacle::operator= (const Obstacle &a) { if(this != &a){ if (p != NULL) delete[]p; p = new Point[a.n]; for (int i = 0; i < a.n; i++)p[i] = a.p[i]; n = a.n; } return *this; } inline const Obstacle operator+(Obstacle &a, const Obstacle &b){ return a+=b; } // Adds the Point(x,y) onto the end of the array of points p void Obstacle::addPoint(int x, int y) { Point *temp = new Point[n]; for (int i = 0; i < n; i++) temp[i] = p[i]; if (p != NULL) delete[] p; p = new Point[n+1]; for (int i = 0; i < n; i ++) p[i] = temp[i]; p[n].x = x; p[n].y = y; if (temp != NULL)delete[] temp; n++; } thanks, Dan |
||||
|
||||
![]() Jingo Member since: 11/2/2003 From: Bath, United Kingdom |
||||
|
|
||||
| What are you doing in the objects constructors/destructors? Post the code. |
||||
|
||||
![]() danbis_uk Member since: 7/21/2004 From: United Kingdom |
||||
|
|
||||
| I just did. Scroll down and they are the first two functions. |
||||
|
||||
![]() Kippesoep Member since: 10/25/2001 From: Etten, Netherlands |
||||
|
|
||||
Quote: There is no reason to check for NULL before deleting. Deleting a NULL pointer is a valid operation (which does absolutely nothing and will not crash). If you get a problem with your delete operation, then it is because you're either deleting something that shouldn't be (invalid pointer or already deleted) or memory has been overwritten somewhere. Kippesoep |
||||
|
||||
![]() danbis_uk Member since: 7/21/2004 From: United Kingdom |
||||
|
|
||||
| Thanks for that Kippesoep. I have removed all checks for Null pointers. Unfortunatley there is something else causing memory problems. It only crashes on completion of the program. |
||||
|
||||
![]() Jingo Member since: 11/2/2003 From: Bath, United Kingdom |
||||
|
|
||||
| Well you implemented operator+ incorrectly, the first argument should not have a reference parameter if you use the method i suggested, probably better using snk_kids version, it is clearer. The code is pretty hard to follow, it looks like you are trying to implement a sizeable array of some kind, std::vector already exists for this purpose, would be better off using that, and you could forget about the memory worries you are having. That said, you are doing a lot of needless copying in the code, Point *temp = new Point[n]; for (int i = 0; i < n; i++) temp[i] = p[i]; if (p != NULL) delete[] p; for example, could be rewritten as Point *temp = p; In both functions. As mentioned above, the deleting of a null pointer is also fine, do not need to check for that in the code. The best advice i could give would be to use std::vector, or use the debugger to step through the code until you find the point at which it crashes. |
||||
|
||||
![]() danbis_uk Member since: 7/21/2004 From: United Kingdom |
||||
|
|
||||
| ive managed to solve it by removing 'delete[] p' from the destructor and therefore leaving it empty. I have no idea why though. Wouldn't this cause problems later on? |
||||
|
||||
![]() Jingo Member since: 11/2/2003 From: Bath, United Kingdom |
||||
|
|
||||
| Yes it would be a problem, it would leak all the memory. The problem is no doubt inside your copy constructor, you need to define one to perform a deep copy, the implicit one is just copying the pointer to the address, and your destructor is calling operator delete on the memory twice, causing the program to crash. |
||||
|
||||
![]() Jingo Member since: 11/2/2003 From: Bath, United Kingdom |
||||
|
|
||||
If you insist on not using std::vector, this code should do it.Obstacle::Obstacle(const Obstacle &a) :p(new Point[a.n]), n(a.n){ for (int i = 0; i < n; ++i) p[i] = a.p[i]; return *this; } |
||||
|
||||
![]() danbis_uk Member since: 7/21/2004 From: United Kingdom |
||||
|
|
||||
| aha that makes sense, i shall work on a copy constructor. Thanks very much well i would have done if you hadn't already done it for me:) thanks |
||||
|
||||
All times are ET (US)![]() |
Last Thread Next Thread ![]() |
|