Chris
Chris

Reputation: 239

Restricting object copy in c++

class adapter
{
     private:
    adapter& operator= (adapter& j)
    {
    cout<<"i m here"<<endl;
    }

    adapter(adapter&)
    {}

    public:
    adapter()
    {}
 };

 int main()
  {

    adapter* p = new adapter;

    adapter* q = new adapter;

    p = q;

    return 0;

  }

Here when q is assigned to p, it should throw compile time error because I have overloaded assignment operator in private section. But my compilation goes well. Anything I am missing here or doing wrong??

Upvotes: 0

Views: 166

Answers (4)

kfsone
kfsone

Reputation: 24249

This is because you are not copying instances, but pointers. Infact, you are losing the pointer to one of your instances.

adapter* p = new adapter;
// translates to:
// void* ptr = alloc(sizeof(adapter));
// adapter* p = (adapter*)ptr;
// new (p) adapter(); // invoke the object's ctor.

adapter* q = new adapter;
// that allocated a new adapter on the heap and ctor'd it.

adapter x;
// this created an actual instance of adapter on the stack;
// when 'x' goes out of scope, because it's on the stack,
// it will be destroyed and it's destructor invoked.
adapter y;
// again, on the stack.

p = q;
// that copied the address of the second allocation into
// the first pointer, *losing* the first pointer. C++ does
// not have garbage collection, so this is called a leak.

x = y; // error: tried to use copy operator.
// this attempts to copy the instance "y" to the instance "x".

In addition to this, you also need to get the right fingerprint for the copy operator and ctor:

private:
    adapter& operator=(const adapter&);
    adapter(const adapter&);

See: http://ideone.com/K4rQdx

class adapter
{
private:
    adapter& operator= (const adapter& j);
    adapter(const adapter&);

public:
    adapter()
    {}
};

int main()
{
    adapter* p = new adapter;
    adapter* q = new adapter;

    *p = *q;

    return 0;
}

If you want to prevent copying of pointers, you'll need to create a class to encapsulate them, or you'll want to look at std::unique_ptr.


Edit:

Prior to C++11 the normal pattern for "disabling" an operator is to leave it undefined:

private:
    adapter& operator = (const adapter&); // name the parameter or not, it's optional.

If someone tries to use it from outside the class, you'll get a compile time privacy error. If something inside the class tries to use it, you'll get a linker error (which is fine when you're expecting it but a headache when you're in crunch trying to fix a release-postponing issue and it's complaining about an undefined function).

With C++11 you can mark it as deleted, which will result in more specific errors:

public:
    adapter& operator = (const adapter&) = delete;

I've taken to making these public because some of the compiler versions I work with check the visibility first leading to old-style errors, whereas making it public allows them to reach the "hey, this is disabled" and give you the newer, more helpful errors they have when they encounter a delete'd function/operator.

Upvotes: 6

stefan
stefan

Reputation: 10345

p and q aren't adapters, but adapter*, that is pointer to adapter.

Worst of all, you're leaking memory:

int main()
{
  adapter* p = new adapter; // first object of type adapter, p points to it
  adapter* q = new adapter; // second object of type adapter, q points to it
  p = q; // both p and q point to the second object now, first object lost
  // no delete statement, so second object lost too.
  return 0;
}

What you should do is either

int main()
{
   adapter p;
   adapter q;
   p = q; // won't compile
}

or

int main()
{
    std::unique_ptr<adapter> p = new adapter;
    std::unique_ptr<adapter> q = new adapter;
    p = q; // won't compile as unique_ptrs don't want you to let two variables point to the same thing
    p = std::move(q); // will compile as you invoke the move-assignment operator.
}

I recommend using the first way.

Upvotes: 1

Martin
Martin

Reputation: 3472

You are only copying the address of adapter object.

Upvotes: 0

Paul Mitchell
Paul Mitchell

Reputation: 3281

You're not copying the adapter object, you're just copying the pointer. Try *p = *q.

Upvotes: 4

Related Questions