views:

175

answers:

4

Lets say we create an object of class Student, we create two instances/objects class Student(i.e. StudentA and StudentB). We do shallow copy to initialize data members of B with that of A as follows:

Student StudentB = StudentA;

And then we destroy StudentB. Are we facing a situation of Dangling Pointer here? Why and how? Please explain.

+3  A: 

Shallow copy isn't discouraged, exactly - it's a matter of knowing when it's appropriate.

The issue here is one of "ownership". Does the "Student" class "own" the pointed-to data, and therefore take responsibility (in its destructor) for deleting that data.

Basically, if you take a shallow copy of an object that owns some pointed-to data, then destruct either the original or the copy, the pointed-to data is deleted (by the destructor). But you still have a reference in the object that wasn't destructed - a dangling pointer.

OTOH, if the object doesn't own the pointed-to data, the destructor doesn't delete the pointed-to data, and there is no problem. Though you do have to ensure that something owns the pointed-to data, or you'll have a memory leak.

Keeping track of ownership of pointed-to data is a key skill in non-garbage-collected languages like C++, and is fundamental to applying the Resource Allocation Is Initialisation pattern.

Steve314
+5  A: 

Are we facing a situation of Dangling Pointer here? Why and how? Please explain.

It depends on the implementation of Student. If Student looks like this ...

class Student
{
public:
  char* m_name;
  Student(const char* name)
  {
    m_name = new char[strlen(name)+1];
    strcpy(m_name,name);
  }
  ~Student()
  {
    delete[] m_name;
  }
};

... then there's a problem: when you copy a Student then you have two pointers to the same m_name data, and when the two Student instances are deleted then the m_name data is deleted twice, which is illegal. To avoid that problem, Student need an explicit copy constructor, so that a copied Student has a pointer to different m_name data.

Alternatively if Student looks like this ...

class Student
{
public:
  std::string m_name;
  Student(const char* name)
    : m_name(name)
  {
  }
};

... then there's no problem because the magic (i.e. an explicit copy constructor) is implemented inside the std::string class.

In summary, you need an explicit copy constructor (or explicitly no copy constructor, but in either case not just the default constructor) if the class contains a pointer which it allocates and deletes.

ChrisW
+1  A: 

To put it simple: If your class member variables contains a pointer which it also owns.

Viktor Sehr
Except that deep copy isn't necessary if the pointer is to data which is neither allocated nor deleted by the class, i.e. to data whose lifetime isn't managed the class.
ChrisW
+1  A: 

Another point is when the pointed data of members is immutable. It is not observable that you share it across instances by using reference counted smart pointers. For example, i have some code that looks like

struct SizeContainer {
  // ... stuff ...
private:
  boost::shared_ptr<SizeExpression> p;
};

I didn't declare a copy constructor and copy assignment operator, because you cannot change p anyway, so it can be shared across multiple instances.

Johannes Schaub - litb