copy on write using a pointer on integer - c++

I try to implement copy on write using a pointer on integer. But I don't understand how to write the code. The idea is very clear in my head: when I use the default constructor, I create a new instance of the object (number of instances=1) and when I use the copy constructor, I increment the number of instances and make a shallow copy of the object.
class Myclass
{
public:
Myclass(const char * foo, int foo2) : foo(foo), foo2(foo2)
{
(*ref)=1;
}
Myclass(const Myclass& rhs) :foo(rhs.foo),foo2(rhs.foo2)
{
(*ref)++;
}
const char * foo;
int foo2;
int *ref;
};
I begin with C++ and the notion of pointer is completely news for me so I tried this.
But I really don't understand why "ref" is still equal to 1 even if I create a copy of the object witht he copy constructor.

Your default constructor needs to create a new reference count:
ref(new int(1))
And your copy constructor needs to make the new object end up with a pointer to the original object's reference count and to increment it (which you already do):
ref(rhs.ref)

I'm having trouble understanding what you want but I'll try...
I create Myclass foo ("foo",10) and then Myclass foo2(foo). I want
all ref to be equal to 2. Here only the ref of foo2 is equal to 2.
The ref of foo is equal to 1. I think I need a pointer, no?
This can be accomplished with a static variable:
class Myclass
{
public:
Myclass(const char * foo, int foo2) : foo(foo), foo2(foo2)
{
ref += 1;
if (1 == ref) {} // First ref, do something?
}
Myclass(const Myclass& rhs) :foo(rhs.foo),foo2(rhs.foo2)
{
ref += 1;
}
~Myclass() // Decrement on delete
{
ref -= 1;
if (0 == ref) {} // Last reference. Do something?
}
const char * foo;
int foo2;
static int ref;
};
int Myclass::ref = 0; // Initialize to 0
Then....
Myclass foo("foo",10); // ref becomes 1
Myclass foo2(foo); // ref becomes 2
Myclass *foo3 = new Myclass(foo); // ref becomes 3
delete foo3; // ref becomes 2

Related

Assignment operator as copy constructor

Assignment operator can be used to copy the value of one object to another
instead of using copy constructor,then why we required a copy constructor?
class example
{
int data;
public:
example()
{
}
example(int x)
{
data = x;
}
};
int main()
{
example a(50);
example a(b);
//same can be done with the assignment operator
//b = a;
return 0;
}
Because at the point of calling a copy constructor, the object being copied to doesn't yet exist.
An assignment operator assigns the value of another object to one that does exist.
Devices such as member initialisation can be used with a copy constructor, but are not available on assignment. Furthermore it's possible to create a const object using a copy constructor.
Furthermore, the assignment operator typically returns a reference to self.
So a copy constructor and the assignment operator probably will leave the mutated object in an identical state, but it doesn't necessarily have to be the case.
As Bathsheba already said: A copy constructor creates a new object, an assignment operator assigns values to an already existing object. One needs to construct a new object, the other needs to handle whatever happens if you assign the values from one object to another. Take this example:
class Foo
{
public:
Foo(int x) { someValue = x; };
int getValue() const { return someValue; };
private:
int someValue;
}
class Bar
{
public:
Bar(int y)
{
myFoo = new Foo(y);
myValue = y + 1;
myInitDone = true;
};
Bar(const Bar& other)
{
//myFoo was not yet initalized, so no need to clean it up
myFoo = new Foo(other.myFoo->getValue());
myValue = other.myValue;
myInitDone = true;
}
Bar& operator=(const Bar& other)
{
delete myFoo; // If we don't clean up myFoo here we leak memory
myFoo = new Foo(other.myFoo->getValue());
myValue = other.myValue;
// myInitDone is only set during construction due to [reason]
}
private:
Foo* myFoo;
int myValue;
bool myInitDone;
}
The copy constructor needs to set myInitDone (which is only done during constuction because [insert reason here]), while the assigment operator needs to clean up myFoo or it will leak memory.

Assigning structs including pointers

Consider the following simple program. It just defines two variables A and B from MyStruct and then initializes A.
How can I copy A to B with new pointers for B?
If I use assignment operator, firstMember of B will be assigned with firstMember of A and whenever I change the value of B.firstMember[i], the value of A.firstMember[i] will change. I already know that it can be done with a function, but is there any simpler way? Assuming that MyStruct can have lots pointers, writing a function doesn't seem to be good.
typedef struct MyStruct
{
int * firstMember;
int secondMember;
} MyStruct;
int main()
{
MyStruct A;
MyStruct B;
Initialize(A); // initializes A such that A.firstMember[0] != 5
B = A;
B.firstMember[0] = 5;
cout<<A.firstMember[0]; // prints 5
return 0;
}
This falls into the "Rule of 3". Once you start managing raw pointers inside a class, you probably want to define a custom contructor, destructor, and assignment operator for this very reason.
First of all, I don't understand why among two members, one is a pointer, and other is not. I am presuming that the first member which is a pointer points to a single integer. Here's an improved code snippet for the structure:
struct MyStruct
{
int * firstMember;
int secondMember;
MyStruct& operator = (const MyStruct& src) {
*firstMember = *src.firstMember;
return *this;
}
MyStruct(int a = 0) {
firstMember = new int(a);
secondMember = a;
}
MyStruct(const MyStruct& src) {
// deep copy
firstMember = new int(*src.firstMember);
secondMember = src.secondMember;
}
~MyStruct() {
if (firstMember)
delete firstMember;
}
};
Note, struct is a class with all members declared as public by default. Rather than having Initialize in C-way, better to use C++ proper construct like constructor, and you need to have copy constructor and assignment operator too.

classes with pointer members and no overridden copy constructor

When pointers point to something declared in the same class, am I right in thinking that if you copy such an object that there are multiple sets of pointers but they all point to the same object(s)?
Does this mean there are other objects in the other class instances that have been created but that nothing is pointing to?
And as a side question, would I be right in thinking that a shared pointer would point all the classes at ONE set of objects but in a safe way?
yes - when you don't define a copy constructor the compiler will issue one for you - which will do a shallow copy - just copy the values(i.e the address) of the pointers.
So the two objects(original and 'copy') will have pointer fields pointing at the same object.
If you don't deep copy the object i.e. if you don't override the copy c'tor and do a shallow copy, the pointer(s) will point to the same instance of an object. If you then delete one of the shallow - copied objects then the pointers of the other objects will point to garbage. If you dereference them in any way your program will crash.
Same thing can happen with the assignment operator. So when you have pointers overload them both.
An example:
struct Message
{
Message(const LogType_E & type_in = LOG_ERROR, const unsigned int & domain_in = 0, const int & msgId_in = 0, const char * msg_in = "");
int myMsgID; //!< message id
unsigned int myDomain; //!< message domain
LogType_E myType; //!< message type
char * myMsg; //!< actual message
~Message()
{
if(myMsg != NULL) delete [] myMsg;
}
Message(const Message &);
const Message& operator=(const Message & rhs);
};
This is a "message" type used to hold a message with other thingies.
Implementation would look like :
Message::Message(const Message & cp_in):myType(cp_in.myType), myDomain(cp_in.myDomain), myMsgID(cp_in.myMsgID), myMsg(NULL)
{
if(cp_in.myMsg != NULL)
{
myMsg = new char[strlen(cp_in.myMsg)+1];
memcpy (myMsg, cp_in.myMsg, strlen(cp_in.myMsg)+1);
}
}
const Message & Message::operator =(const AX::Base::Log::Message &cp_in)
{
if (this == &cp_in) // protect against invalid self-assignment
return *this;
//deallocate old memory
if(myMsg != NULL) delete [] myMsg;
if(cp_in.myMsg != NULL)
{
//allocate new memory and copy the elements
myMsg = new char[strlen(cp_in.myMsg)+1];
memcpy (myMsg, cp_in.myMsg, strlen(cp_in.myMsg)+1);
}
// copy other data members
myType = cp_in.myType;
myDomain = cp_in.myDomain;
myMsgID = cp_in.myMsgID;
return *this;
}
That said, please use std::string to avoid all these things - that was just a proof of concept example.
Imagine you have a class like so that exhibits the problem you have asked in the question
class Foo{};
class Bar
{
public:
Foo* mFoo;
Bar() : mFoo( new Foo() ) {}
~Bar() { delete mFoo;}
};
And code like so
Bar x ;
Bar y = x;
The above code will cause an core dump because both y and x will point to the same Foo and the destructor will try to delete the same Foo twice.
ALTERNATIVE 1
Declare but not provide a definition so that Bar is never copy constructor or assigned. The will ensure that Bar y = x will have a link error as you have designed the class not be copied.
class Bar
{
public:
Foo* mFoo;
Bar() : mFoo( new Foo() ) {}
~Bar() { delete mFoo;}
Bar(const Bar &);
Bar& operator= (const Bar &);
};
ALTERNATIVE 2
Provide a copy constructor and assignment operator that do the right thing. Instead of the compiler provided default implementation of copy and assignment that do shallow copy you are duplicating Foo so that both x and y have their own Foo
class Bar
{
public:
Foo* mFoo;
Bar() : mFoo( new Foo() ) {}
~Bar() { delete mFoo;}
Bar(const Bar & src)
{
mFoo = new Foo( *(src.mFoo) );
}
Bar& operator= (const Bar & src)
{
mFoo = new Foo( *(src.mFoo) );
return *this;
}
};
ALTERNATIVE 3 (BEST)
Use C++11 shared_ptr or boost and omit the copy and assigment as the default compiler provided one will do the right thing as shared_ptr is ref counted and will delete Foo only once even though both x and y share the same Foo. Also notice that ~Bar needs to no explicit clean up as mFoo will automatically be deleted in std::shared_ptr<Foo> destructor when the the refcount of Foo becomes zero.
class Bar
{
public:
std::shared_ptr<Foo> mFoo;
Bar() :mFoo( new Foo() ) {}
~Bar() { }
};
Let the code do the talking to clear things up:
struct X
{
int data;
int *ptr;
X() : ptr(&data) {}
};
X a;
X b = a; // yes, `a.ptr` points to `b.data`!
Indeed, the pointers will be copied verbatim and will keep pointing into the source of the copy.
Use pointer-to-members
Fixable thus:
struct X
{
int data;
int X::*ptr;
X() : ptr(&X::data) {}
};
X a;
X b = a; // now, `a.ptr` points to `a.data`
Extending this sample with some more usage hints https://ideone.com/F0rC3
a.ptr = &X::data2; // now `a.ptr` points to `a.data2`
// `b.ptr` points to `b.data1`
b = a; // `b.ptr` points to `b.data2` too
// Usage hint:
int deref = a.*(a.ptr); // gets the field pointed to by a.ptr, from the instance a
deref = b.*(b.ptr); // gets the field pointed to by b.ptr, from the instance b
// but of course you could get fancy and do
deref = a.*(b.ptr); // gets the field pointed to by b.ptr, **but** from the instance a
That would do what you probably want. Although, why you want that is beyond me (and beyond C++, possibly)

C++ : Implementing copy constructor and copy assignment operator

After reading about copy constructors and copy assignment operators in C++, I tried to create a simple example. Though the below snippet apparently works, I am not sure whether I am implementing the copy constructor and copy assignment operator the right way. Could you please point out if there are any mistakes/improvements or a better example to understand the relevant concepts.
class Foobase
{
int bInt;
public:
Foobase() {}
Foobase(int b) { bInt = b;}
int GetValue() { return bInt;}
int SetValue(const int& val) { bInt = val; }
};
class Foobar
{
int var;
Foobase *base;
public:
Foobar(){}
Foobar(int v)
{
var = v;
base = new Foobase(v * -1);
}
//Copy constructor
Foobar(const Foobar& foo)
{
var = foo.var;
base = new Foobase(foo.GetBaseValue());
}
//Copy assignemnt operator
Foobar& operator= (const Foobar& other)
{
if (this != &other) // prevent self-assignment
{
var = other.var;
base = new Foobase(other.GetBaseValue());
}
return *this;
}
~Foobar()
{
delete base;
}
void SetValue(int val)
{
var = val;
}
void SetBaseValue(const int& val)
{
base->SetValue(val);
}
int GetBaseValue() const
{
return(base->GetValue());
}
void Print()
{
cout<<"Foobar Value: "<<var<<endl;
cout<<"Foobase Value: "<<base->GetValue()<<endl;
}
};
int main()
{
Foobar f(10);
Foobar g(f); //calls copy constructor
Foobar h = f; //calls copy constructor
Foobar i;
i = f;
f.SetBaseValue(12);
f.SetValue(2);
Foobar j = f = z; //copy constructor for j but assignment operator for f
z.SetBaseValue(777);
z.SetValue(77);
return 1;
}
Your copy assignment operator is implemented incorrectly. The object being assigned to leaks the object its base points to.
Your default constructor is also incorrect: it leaves both base and var uninitialized, so there is no way to know whether either is valid and in the destructor, when you call delete base;, Bad Things Happen.
The easiest way to implement the copy constructor and copy assignment operator and to know that you have done so correctly is to use the Copy-and-Swap idiom.
Only Foobar needs a custom copy constructor, assignment operator and destructor. Foobase doesn't need one because the default behaviour the compiler gives is good enough.
In the case of Foobar you have a leak in the assignment operator. You can easily fix it by freeing the object before allocating it, and that should be good enough. But if you ever add a second pointer member to Foobar you will see that that's when things get complicated. Now, if you have an exception while allocating the second pointer you need to clean up properly the first pointer you allocated, to avoid corruption or leaks. And things get more complicated than that in a polynomial manner as you add more pointer members.
Instead, what you want to do is implement the assignment operator in terms of the copy constructor. Then, you should implement the copy-constructor in terms of a non-throwing swap function. Read about the Copy & Swap idiom for details.
Also, the default constructor of Foobar doesn't default-initialize the members. That's bad, because it's not what the user would expect. The member pointer points at an arbitrary address and the int has an arbitrary value. Now if you use the object the constructor created you are very near Undefined Behaviour Land.
I have a very simple patch for you:
class Foobar
{
int var;
std::unique_ptr<FooBase> base;
...
That should get you started.
The bottom line is:
Don't call delete in your code (Experts see point 2)
Don't call delete in your code (you know better...)

Is this C++ reassignment valid?

Sorry for the basic question, but I'm having trouble finding the right thing to google.
#include <iostream>
#include <string>
using namespace std;
class C {
public:
C(int n) {
x = new int(n);
}
~C( ) {
delete x;
}
int getX() {return *x;}
private:
int* x;
};
void main( ) {
C obj1 = C(3);
obj1 = C(4);
cout << obj1.getX() << endl;
}
It looks like it does the assignment correctly, then calls the destructor on obj1 leaving x with a garbage value rather than a value of 4. If this is valid, why does it do this?
If there is a class C that has a constructor that takes an int, is this code valid?
C obj1(3);
obj1=C(4);
Assuming C has an operator=(C) (which it will by default), the code is valid. What will happen is that in the first line obj1 is constructed with 3 as a the parameter to the constructor. Then on the second line, a temporary C object is constructed with 4 as a parameter and then operator= is invoked on obj1 with that temporary object as a parameter. After that the temporary object will be destructed.
If obj1 is in an invalid state after the assignment (but not before), there likely is a problem with C's operator=.
Update: If x really needs to be a pointer you have three options:
Let the user instead of the destructor decide when the value of x should be deleted by defining a destruction method that the user needs to call explicitly. This will cause memory leaks if the user forgets to do so.
Define operator= so that it will create a copy of the integer instead of a copy of the value. If in your real code you use a pointer to something that's much bigger than an int, this might be too expensive.
Use reference counting to keep track how many instances of C hold a pointer to the same object and delete the object when its count reaches 0.
If C contains a pointer to something, you pretty much always need to implement operator=. In your case it would have this signature
class C
{
public:
void operator=(const C& rhs)
{
// For each member in rhs, copy it to ourselves
}
// Your other member variables and methods go here...
};
I do not know enough deep, subtle C++ to explain the problem you are encountering. I do know, however, that it's a lot easier to make sure a class behaves the way you expect if you follow the Rule of Three, which the code you posted violates. Basically, it states that if you define any of the following you should define all three:
Destructor
Copy constructor
Assignment operator
Note as well that the assignment operator implementation needs to correctly handle the case where an object is assigned to itself (so-called "self assignment"). The following should work correctly (untested):
#include <iostream>
#include <string>
using namespace std;
class C {
public:
C(int n) {
x = new int(n);
}
C(const C &other): C(other.getX()) { }
~C( ) {
delete x;
}
void operator=(const C &other) {
// Just assign over x. You could reallocate if you first test
// that x != other.x (the pointers, not contents). The test is
// needed to make sure the code is self-assignment-safe.
*x = *(other.x);
}
int getX() {return *x;}
private:
int* x;
};
void main( ) {
C obj1 = C(3);
obj1 = C(4);
cout << obj1.getX() << endl;
}
Basically you are trying to re-implement a smart pointer.
This is not trivial to get correct for all situations.
Please look at the available smart pointers in the standard first.
A basic implementation (Which will fail under certain situations (copy one of the standard ones to get a better one)). But this should cover the basics:
class X
{
int* data;
public:
// Destructor obvious
~X()
{
delete data;
}
// Easy constructor.
X(int x)
:data(new int(x))
{}
// Copy constructor.
// Relatively obvious just do the same as the normal construcor.
// Get the value from the rhs (copy). Note A class is a friend of
// itself and thus you can access the private members of copy without
// having to use any accessor functions like getX()
X(X const& copy)
:data(new int(copy.x))
{}
// Assignment operator
// This is an example of the copy and swap idiom. This is probably overkill
// for this trivial example but provided here to show how it is used.
X& operator=(X const& copy)
{
X tmp(copy);
this->swap(tmp);
return this;
}
// Write a swap() operator.
// Mark it is as no-throw.
void swap(X& rhs) throws()
{
std::swap(data,rhs.data);
}
};
NEW:
What's happening is that your destructor has deallocated the memory allocated by the constructor of C(4). So the pointer you have copied over from C(4) is a dangling pointer i.e. it still points to the memory location of the deallocated memory
class C {
public:
C(int n) {
x = new int(n);
}
~C( ) {
//delete x; //Don't deallocate
}
void DeallocateX()
{
delete x;
}
int getX() {return *x;}
private:
int* x;
};
int main(int argc, char* argv[])
{
// Init with C(3)
C obj1 = C(3);
// Deallocate C(3)
obj1.DeallocateX();
// Allocate memory and store 4 with C(4) and pass the pointer over to obj1
obj1 = C(4);
// Use the value
cout << obj1.getX() << endl;
// Cleanup
obj1.DeallocateX();
return 0;
}
Be explicit about ownership of pointers! auto_ptr is great for this. Also, when creating a local don't do C obj1 = C(3) that creates two instances of C and initializes the first with the copy constructor of the second.
Heed The Guru.
class C {
public:
C(int n) : x(new int(n)) { }
int getX(){ return *x; }
C(const C& other) : x(new int(*other.x)){}
C& operator=(const C& other) { *x = *other.x; return *this; }
private:
std::auto_ptr<int> x;
};
int main() {
C obj1(3);
obj1 = C(4);
std::cout << obj1.getX() << std::endl;
}
When are you testing the value of obj1? Is it after you leave the scope?
In your example, obj1 is a stack object. That means as soon as you leave the function in which it defined, it gets cleaned up (the destructor is called). Try allocating the object on the heap:
C *obj1 = new C(3);
delete obj1;
obj1 = new C(4);