Hi , There:
I just have a simple question by programming.
Looks like this:

class A{
.....
.....
Public:
   copy(){
      return *(this); 
   }

}

in .cc file: for example we have a container

list<A> list;
A* a = new A(...);
list.push_back(a->copy());

Why is this copy() better than not use it .
I guess, if we use this copy(), then needn't to free this pointer.
But really don't know ,why ......

Any suggestion will be appreciated .

Thx
Teddy

Recommended Answers

All 8 Replies

The default copy constructor does only minimal thigs -- it is not sufficnet for most classes that contain objects of complex types such as pointers and container classes.

I don't know where you got that code, but it is wholly ineffective. It uses the copy constructor whether you like it or not.

Further, you left the return type off of the copy() function (so it wouldn't compile). If you declare it as: A &copy(); then you'll wind-up with two copies of a. If you declare it as: A copy(); you'll produce three copies of a (one a temporary used in the assignment).

In all cases, the first a that you created with new still needs to be explicitly deleted. Otherwise you'll have a memory leak.

The problem with the default copy constructor that Ancient Dragon alluded to is that it makes a byte-for-byte copy of your object. If your object news variables, etc., then what you get using the default copy constructor is two objects that use the exact same data. So what happens if one object deletes that data? Then the other tries to use or delete it, and your program crashes.

If you want to read more on this, google "shallow vs deep copy".

BTW. Don't name lists "list" or arrays "array".

Oh, yeah, also. If you really want to just pass a pointer off, use a list of pointers:

list<A*> ls;
A *a = new A( ... );
ls.push_back( a );

This works just fine. Your object is never copied (the pointer to the object is copied). You still have to remember to delete each object in the list, though.

Hope this helps.

Thanks a lot for both ur help !!
I think i have gotten what u meant.
"Deeply Copy" makes me first understood.
And,
Here, If i have this:

A* a = new A(...);
ls.push_back(a->copy());
delete a;

That means i just push a Object in container, instead of Pointer.
Right ??? then, it works with no mem leaks.

Thx
Teddy

Sure. That works.

Sure. That works.

Does it? push_back only makes a copy of the pointer, the memory is still allocated to the original pointer which is deleted immediately after the push_back. Now list has an invalid pointer and any attempt to dereference it will fail.

No, the whole point is that copy() returns an implicitly copy-constructed copy of *a. Hence, *a is completely out of the equation by the time push_back() gets its piece.

Again, this is assuming copy() returns either A or A& (consistent with the return *(this); line above).

And again, as AD said, if A has any deep data at all, this will still fail, because the data that the copies of *a point to is the same data that *a points to. Once you delete a the deep data disappears also, leaving all copies of *a pointing to invalid data.

Here's an example to play with.

#include <iostream>
#include <string>
#include <list>
#include <cstring>
using namespace std;

int counter = 0;

class A {
  private:
    char *deep_data;
    int count;

  public:
    A( bool make_me_deep ) {
      count = counter++;
      cout << "Constructor: " << count << " as " << (make_me_deep ? "deep." : "shallow.") << endl;

      if (make_me_deep) {
        deep_data = new char[ 1000 ];
        strcpy( deep_data, "Knight to C3" );
        }
      else              deep_data = NULL;
      }

    ~A() {
      cout << "Destructor: " << count << endl;
      if (deep_data) delete[] deep_data;
      }

    A( const A& a ) {
      // simulate default copy constructor
      deep_data = a.deep_data;
      count     = a.count + 10;

      cout << "copied " << a.count << " as " << count << endl;
      }

//    A copy() {
    A &copy() {
      return *(this);
      }

    void hello() {
      char *s;
      if (deep_data) s = deep_data;
      else           s = "Does that cloud look like a flower to you?";
      cout << endl << count << " says \"" << s << '\"' << endl;
      }

    void deepmodify() {
      sprintf( deep_data, "%s%d%s",
        "PWND BY ",
        count,
        "!!!!"
        );
      }
  };

int main() {
  list<A> ls;
  A *a;

  cout << "(Create shallow and shallow copy it)" << endl;
  a = new A( false );

  ls.push_back( a->copy() );

  delete a;

  ls.front().hello();


  cout << "\n(Create deep and shallow copy it)" << endl;
  a = new A( true );

  ls.push_back( a->copy() );

  ls.back().hello();

  cout << "\n(Modify the original deep here)" << endl;
  a->deepmodify();

  ls.back().hello();

  cout << "\n(Delete the original deep)" << endl;
  delete a; // Danger Will Robinson!

  ls.back().hello();

  cout << "\n(Well, that last statement from 11 should have" << endl
       << "caused a core-dump. Lucky you you're still here." << endl
       << "So, enjoy the automatic cleanup of the list<A>):" << endl;

  return 0;
  }

Somehow it survives to the end on my XP box, but that's undefined behavior. (Something keeps it from faulting when attempting to read the deleteed data on my sys...)

In any case, list<> understands that it keeps a pointer to things, and manages to handle stuff sufficiently transparently to the user. So if you pass it a reference you don't need to worry about freeing it...

Hope this helps.

Hi,
you writhing copy function.. in that function we should mantain the parameter as const bcoz before executing any context switch will occer that any thread can modify the members of that object...

and this copy function is provided by compiler... if your writing means your overwritting that function... internally it ll return the this pointer we no need to return the this pointer externally...

you writhing copy function.. in that function we should mantain the parameter as const bcoz before executing any context switch will occer that any thread can modify the members of that object...

? What are you talking about? (Threads? You should know better than to share objects across threads!)

and this copy function is provided by compiler... if your writing means your overwritting that function... internally it ll return the this pointer we no need to return the this pointer externally...

Now you've totally lost me. Are you talking about A( const A& a ) or A &copy() ?

"Internally" it does exactly what it says. this is a pointer to myself. *this is me.
If I return this I get another pointer to myself.
If I return *this I get another me.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.