3

How do I remove double (delete) errors from shallow copied object vs original object.

A simple example:

class INT
{
   int *p; //dynamic.

   //define here fancy constructors etc.
   set(int i){ p=new int; p=i;}
   ~INT();
}

INT::~INT()
{
   if(p) delete p;
}

void somefunction(INT a)
{
   //done some stuff ,e.g. call some display function
}
//note here, that a destructor will be called, and a.p will vanish.

int main(void)
{
   INT a; a.set(2);
   somefunction(a);//shallow copy
}
//CRASH BOOM BOOM!

I would like a generic solution, because passing objects is a trivial thing, and something as naive as this, resulting into a horrific/terrific error is just 'awesome'.

I suspect there are many ways around this (some of which even I can think of), but I was curious if there is any generic (applicable almost everywhere) way of solving this problem?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
nikhilelite
  • 301
  • 1
  • 4
  • 16
  • possible duplicate of [What is the copy-and-swap idiom?](http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom) – Mike Seymour Mar 11 '11 at 02:31
  • possible duplicate of [What is The Rule of Three?](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – Ben Voigt Mar 11 '11 at 02:32
  • note: I do not want to use references , or is using references the generic solution ? – nikhilelite Mar 11 '11 at 02:51
  • @nik: First off, I don't see where someone said anything about references. That said, if they did, why wouldn't you use them? They're a critical language feature (required for copy-constructors, in fact), and avoiding them is silly. You need to write a copy-constructor and assignment-operator (that's what the rule of three Q&A talks about), and the best way to do that is with the copy-and-swap idiom (which the copy-and-swap Q&A talks about). (Or you may disable copying and assignment altogether, as the rule of three Q&A mentions). Or simply avoid dynamic allocation. – GManNickG Mar 11 '11 at 03:00
  • ok, so for a huge dynamic resource it seems following is better way: 1. Disable copy and = operators 2. use references in functions that make use of object (to avoid pass by value, or shallow copy) – nikhilelite Mar 11 '11 at 03:08
  • @nik: Yes. In general, pass everything by reference unless it's a built-in type, or unless you need a copy for yourself. – GManNickG Mar 11 '11 at 03:13

4 Answers4

5

Whenever you have apointer object inside your class then you need to declare your own copy constructor and assignment operator method to avoid shallow copy problem. Look ate this link for mor info on this

Raghuram
  • 3,937
  • 2
  • 19
  • 25
  • No the problem is, in this case the object is just a simple int, in other cases it might be something far to expensive to copy. – nikhilelite Mar 11 '11 at 02:57
  • @nik: "Big" is a vague word. Again, what measurements? You can't just assume you need to make some optimization, it's a waste of time. Your concern should be learning to program in the most correct way possible. When you're *finished* you may profile your application and get real data that tells you where the slow spots are. Guessing is not data. – GManNickG Mar 11 '11 at 03:12
  • 1
    @nikhilelite if you really want to avoid copying, you should investigate using shared_ptr<> instead of a raw C/C++ pointer. That will make your code simpler and greatly improve the chances of it working correctly. – Jeremy Friesner Mar 11 '11 at 03:28
2

Patient: Doctor, it hurts when I do this!
Doctor: Don't do that.

Chances are at least 100:1 that you can write your code just fine without dealing with a raw pointer. Depending on the situation, you may need a smart pointer or you may need a collection, but the chances that you need a pointer seem quite remote.

Instead of asking about how to fix what you're doing, you'd be much better off telling us what you're trying to accomplish, so we can tell you about how to do that.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Any tips on a conclusive article on these kind of issues. – nikhilelite Mar 11 '11 at 02:59
  • 1
    You haven't really told us what the issue *is* yet. If you want to avoid deep copies, you might want to look into something like Boost's smart pointers: http://www.boost.org/doc/libs/1_46_0/libs/smart_ptr/smart_ptr.htm – Jerry Coffin Mar 11 '11 at 03:06
2

For all objects with dynamic members, it is usually best to define your own copy and copy-assignment operations for just this reason.

Regarding 'big' objects and expensive copying, reference counting is a technique employed by many languages and patterns to circumvent this problem of pointer ownership. Note that all copies of an object point to the same shared object in this case, so a modification of the shared object from one instance will be visible to others. See the boost shared_ptr documentation for more info.

Kyle
  • 321
  • 4
  • 4
1

The question "How do I avoid double delete from shallow copied objects?" should really be "How do I avoid shallow copies, when I don't want that?".

Some options are:
- avoid raw pointers to allocated memory
- don't copy the objects! :-)
- manage the memory outside of the objects
- use a smart pointer
- implement deep copying

Your choice depends on what you are actually using your objects for.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203