Writing a deep copy - copying pointer value - c++

In writing a copy constructor for a class that holds a pointer to dynamically allocated memory, I have a question.
How can I specify that I want the value of the pointer of the copied from object to be copied to the pointer of the copied to object. Obviously something like this doesn't work...
*foo = *bar.foo;
because, the bar object is being deleted (the purpose of copying the object in the first place), and this just has the copied to object's foo point to the same place.
What is the solution here? How can I take the value of the dynamically allocated memory, and copy it to a different address?

You allocate new object
class Foo
{
Foo(const Foo& other)
{
// deep copy
p = new int(*other.p);
// shallow copy (they both point to same object)
p = other.p;
}
private:
int* p;
};

I do not see the context, but the code you posted doesn't seem like copying the pointer, it is exactly what you ask for — copying whatever it points to. Provided that foo points to the allocated object.

I assume your class looks like this.
class Bar {
Foo* foo;
...
}
In order to do a deep copy, you need to create a copy of the object referenced by 'bar.foo'. In C++ you do this just by using the new operator to invoke class Foo's copy constructor:
Bar(const Bar & bar)
{
this.foo = new Foo(*(bar.foo));
}
Note: this solution delegates the decision of whether the copy constructor new Foo(constFoo &) also does a 'deep copy' to the implementation of the Foo class... for simplicity we assume it does the 'right thing'!
[Note... the question as written is very confusing - it asks for the 'value of the pointer of the copied from object' that doesn't sound like a deep copy to me: that sounds like a shallow copy, i.e. this.
Bar(const Bar & bar)
{
this.foo = bar.foo;
}
I assume this is just innocent confusion on the part of the asker, and a deep copy is what is wanted.]

Related

Copy Constructor with assignment overloading syntax?

I am working with writing the big five(copy constructor, copy assignment operator, move constructor, move assignment operator, destructor). And I've hit a bit of a snag with the copy constructor syntax.
Say I have a class foo that has the following private members:
template<class data> // edit
class foo{
private:
int size, cursor; // Size is my array size, and cursor is the index I am currently pointing at
data * dataArray; // edit
}
If I were to write a constructor for this of some arbitrary size X it would look like this.
template<class data> // edit
foo<data>::foo(int X){
size = X;
dataArray = new data[size];
cursor = 0; // points to the first value
}
Now if I wanted to make a copy constructor of another object called bar I'd need to make the following:
template<class data> // edit
foo<data>::foo(foo &bar){
foo = bar; // is this correct?
}
Assuming I have the overloaded = from the code below:
template<class data> // edit
foo<data>::operator=(foo &someObject){
if(this != someObject){
size = someObject.size;
cursor = someObject.cursor;
delete[] dataArray;
dataArray = new data[size];
for(cursor = 0; cursor<size-1;cursor++)
dataArray[cursor] = someObject.dataArray[cursor];
}
else
// does nothing because it is assigned to itself
return *this;
}
Is my copy constructor correct? Or should foo = bar instead be *this = bar ?
I'm still new to templated constructors so if I made any errors in the code please let me know I will correct it.
EDIT 1: Thanks to the answer provided below by Marcin I have made some edits to the code above to make it more syntatically correct and commented them with //edit they are summarized in the list below:
previously template<classname data>, which is incorrect must be template <typename data> or template <class data> for functions and classes respectively.
previously int*dataArray; this missuses the template and should be data* dataArray;
The best way to achieve what you want is to use a class that already handles assignment, copying and moving, taking care of its memory management for you. std::vector does exactly this, and can directly replace your dynamically allocated array and size. Classes that do this are often referred to as RAII classes.
Having said that, and assuming this is an exercise in correctly implementing the various special member functions, I'd suggest that you proceed via the copy and swap idiom. (See What is the copy and swap idiom? on SO, for more details and commentary). The idea is to define the assignment operation in terms of the copy constructor.
Start with the members, constructor and destructor. These define the ownership semantics of the members of your class:
template <class data>
class foo {
public:
foo(const size_t n);
~foo();
private:
size_t size; // array size
size_t cursor; // current index
data* dataArray; // dynamically allocated array
};
template <class data>
foo<data>::foo(const size_t n)
: size(n), cursor(0), dataArray(new data[n])
{}
template <class data>
foo<data>::~foo() {
delete[] dataArray;
}
Here, memory is allocated in the constructor and deallocated in the destructor.
Next, write the copy constructor.
template <class data>
foo<data>::foo(const foo<data>& other)
: size(other.size), cursor(other.cursor), dataArray(new data[other.size]) {
std::copy(other.dataArray, other.dataArray + size, dataArray);
}
(along with the declaration, foo(const foo& other); inside the class body).
Notice how this uses member initialiser lists to set the member variables to the values in the other object. A new allocation is performed, and then in the body of the copy constructor you copy the data from the other object into this object.
Next comes the assignment operator. Your existing implementation has to perform a lot of manipulation of pointers, and isn't exception safe. Let's look at how this could be done more simply and more safely:
template <class data>
foo<data>& foo<data>::operator=(const foo<data>& rhs) {
foo tmp(rhs); // Invoke copy constructor to create temporary foo
// Swap our contents with the contents of the temporary foo:
using std::swap;
swap(size, tmp.size);
swap(cursor, tmp.cursor);
swap(dataArray, tmp.dataArray);
return *this;
}
(along with the declaration in-class, foo& operator=(const foo& rhs);).
[-- Aside: You can avoid writing the first line (explicitly copying the object) by accepting the function argument by value. It's the same thing, and might be more efficient in some cases:
template <class data>
foo<data>& foo<data>::operator=(foo<data> rhs) // Note pass by value!
{
// Swap our contents with the contents of the temporary foo:
using std::swap;
swap(size, rhs.size);
swap(cursor, rhs.cursor);
swap(dataArray, rhs.dataArray);
return *this;
}
However, doing so may cause ambiguous overloads if you also define a move assignment operator. --]
The first thing this does is create a copy of the object being assigned from. This makes use of the copy constructor, so the details of how an object is copied need only be implemented once, in the copy constructor.
Once the copy has been made, we swap our internals with the internals of the copy. At the end of the function body, the tmp copy goes out of scope, and its destructor cleans up the memory. But this isn't the memory that was allocated at the beginning of the function; it's the memory our object used to hold, before we swapped our state with the temporary.
In this way, the details of allocating, copying and deallocating are kept where they belong, in the constructors and the destructor. The assignment operator simply copies and swaps.
This has a further advantage, over and above being simpler: It's exception safe. In the code above, an allocation error could cause an exception to be thrown while creating the temporary. But we haven't modified the state of our class yet, so our state remains consistent (and correct) even when the assignment fails.
Following the same logic, the move operations become trivial. The move constructor must be defined to simply take ownership of the resource and leave the source (the moved-from object) in a well-defined state. That means setting the source's dataArray member to nullptr so that a subsequent delete[] in its destructor doesn't cause problems.
The move assignment operator can be implemented similarly to the copy assignment, although in this case there's less concern with exception safety since you're just stealing the already-allocated memory of the source object. In the complete example code, I opted to simply swap the state.
A complete, compilable-and-runnable example can be seen here.
Your foo class does not internally use data template parameter. I suppose you wanted to use it here:
int * dataArray; // should be: data * dataArray;
You also are not allowed to use classname keyword but typename or class. You have also lots of other compile errors in your code.
Your copy constructor is wrong, it will not compile:
foo = bar; // is this correct? - answer is NO
foo is a class name in this context, so your assumption is correct. *this = someObject this would work (with additional fixes, at least dataArray must be set to nullptr), but your class variables would be default constructed first by copy constructor only to be overwritten by assignment operator, so its quiet non efficent. For more read here:
Calling assignment operator in copy constructor
Is it bad form to call the default assignment operator from the copy constructor?

Reassigning variable, delete called twice (C++)

My programming background is the Java world, but I've just started learning C++. I've stumbled across this rather trivial and probably pretty noobish problem that somehow puzzles me as a Java programmer:
I have a class with an array which is initialized via new in the constructor and deleted in the destructor. Now when I create an object of this class and assign another object of this class to the same variable (at least that is what I think it is), the delete[] method in the destructor seems to be called twice when the variables leave the scope (in this case the main() function) (the debugger gives me an _BLOCK_TYPE_IS_VALID assertion failed warning).
Why is that? Why isn't the deconstructor called before I assign a new object to f? How could I explicitely delete Foo(1)? What exactly happens here?
class Foo{
private:
int *field;
public:
Foo(int size){
field = new int[size];
}
~Foo(){
delete[] field;
}
};
int main(){
Foo f = Foo(1);
f = Foo(2);
}
There is something in the C++ world called the Rule Of Three.
A class will automatically generate a destructor, copy constructor, and assignment operator for you.
If you have to manually define one of those functions, you probably have to define all three of them.
In your case, you should define the two copy functions, so that a copy of Foo gets its own copy of field. Add these two functions:
class Foo{
Foo( const Foo &f ) {
size = f.size;
field = new int[size];
std::copy( f.field, f.field + size, field );
}
Foo& operator=( const Foo &f ) {
// Leverage the logic that was already written in the copy constructor
Foo tmp(f);
std::swap( *this, temp );
return *this;
}
};
Note that I'm assuming that you've stored size in the Foo object. You would probably need to store that information anyway in a real-life application
You're not following the rule of three, which is bad. Because the default copy constructor does a shallow copy, all your automatic variables (f and the temporaries) have the field member pointing to the same int, which is destroyed multiple times when the destructor is called.
Implement a proper copy constructor, or use C++ idioms and avoid manual management alltogether - i.e. use a std::vector instead.

C++ private constant pointer

I am learning pointers in c++ and am having some trouble.
I have a class Foo that in the header file declares some data:
private:
const Bar *obj;
Where Bar is a class.
Then in the c++ implementation I want to replace *obj so that it points to a completely different Bar object. *obj is constant, so how do I change what is in what *obj points to or rather, what is in memory at *obj? Also in Foo's destructor, how do I deallocate *obj?
Given your class definition
class A {
private:
const Bar *obj;
};
obj is a pointer to a constant Bar object. You can change what that pointer points to, but you cannot change the contents of the object pointed to.
So, if you have a new Bar object and you'd like to change obj so it points to that, you can simply assign the new value:
/* New object: */
Bar *new_bar = new Bar;
/* Change the pointer: */
obj = new_bar;
There are two issues, however.
If the new Bar object is created outside the class, you cannot directly assign it to obj because the latter is private. Hence you need a setter function:
class A {
private:
const Bar *obj;
public:
void set_obj(const Bar *new_obj) { obj = new_obj; }
};
You must determine who will eventually own the Bar object, i.e. who is responsible for freeing the heap space it takes. If the caller is responsible then you can code it as above, i.e. class A will never create new Bar objects, nor delete any. It will just maintain a pointer to Bar objects created and deleted outside the class.
But if class A above is actually responsible for the memory space taken by the Bar objects, you must use delete obj in the destructor to free the space, and you must also free the space when you get a new Bar object assigned. That is, the set_obj function above needs to be changed to this:
void set_obj(const Bar *new_obj) { delete obj; obj = new_obj; }
Otherwise you'll have a memory leak. Similar measures must be taken in the copy constructor (unless you delete it), as well as the assignment operator: Both functions are used whenever a copy of a class A object is made, and in that case you must make sure that you do not simply copy the pointer, but instead allocate fresh space and copy the object (i.e. you must perform a deep copy):
A(const A& a):obj(new Bar(*a.obj)) {}
A& operator=(const A& a) { delete obj; obj = new Bar(*a.obj); return *this; }
Having said this, if your class is responsible for the memory space, it is a much better idea to use a smart pointer class instead of a raw pointer. The main reasons are: (i) The above is quite complicated and it's easy to make mistakes; (ii) The above is still not very good – there may still be memory leaks or worse problems when an exception is thrown, e.g. in the constructor of Bar. C++11 provides a smart pointer class called std::unique_ptr, which seems ideal for your purposes:
class A {
private:
std::unique_ptr<const Bar> obj;
public:
~A() {}
void set_obj(std::unique_ptr<const Bar> new_obj) { obj = new_obj; }
};
With this in place, the smart pointer will take care of any memory space that needs to be freed automatically, both at destruction time as well as when a new Bar object is assigned to the pointer.
You cannot use that pointer to to change the value that's being pointed to, that's why it's a const, but you should be able to change what it is pointing to.
On c++ "const Bar *obj;" means that you have a pointer to a readonly Bar object; meaning that you can point it to any readonly Bar object.
You can also point a non constant variable, thus promising that you will not change it using that pointer.
If you want to have a pointer, that is constant in the sense that it can't be made to point anything else, then you should write it this way:
Bar * const obj = some_object;
This will compile and work fine:
const int p = 1, q = 2;
int r = 3;
const int* i = &p;
i = &q; // point it to a different const variable.
i = &r; // point it to a different non const variable.
As written I believe that this is a pointer to a const Bar object and not a constant pointer.

Can a copy-constructor take a non-const parameter?

I have this problem, there is a function foo() as follows,
vector<ClassA> vec;
void foo()
{
ClassA a; //inside foo, a ClassA object will be created
a._ptr = new char[10];
vec.push_back(a); //and this newly created ClassA object should be put into vec for later use
}
And AFAIK, vec will invoke ClassA's copy-ctor to make a copy of the newly created object a, and here is the problem. If I define ClassA's copy-ctor the usual way,
ClassA::ClassA(const ClassA &ra) : _ptr(0)
{
_ptr = ra._ptr;
}
then object a and its copy (created by vec) will have pointers _ptr pointing to the same area, when foo finishes, a will call the destructor to release _ptr, then a's copy in vec will be a dangling pointer, right? Due to this problem, I want to implement ClassA's copy-ctor this way,
ClassA::ClassA(ClassA &ra) : _ptr(0) //take non-const reference as parameter
{
std::swap(_ptr, a._ptr);
}
Is my implementation ok? Or any other way can help accomplish the job?
To answer your titular question: Yes, any constructor for a class T that has one mandatory argument of type T & or T const & (it may also have further, defaulted arguments) is a copy constructor. In C++11, there's also a move constructor which requires one argument of type T &&.
Having a non-constant copy constructor that actually mutates the argument gives your class very unusual semantics (usually "transfer semantics") and should be extensively documented; it also prevents you from copying something constant (obviously). The old std::auto_ptr<T> does exactly that.
If at all possible, the new C++11-style mutable rvalue references and move constructors provide a far better solution for the problem of "moving" resources around when they're no longer needed in the original object. This is because an rvalue reference is a reference to a mutable object, but it can only bind to "safe" expressions such as temporaries or things that you have explicitly cast (via std::move) and thus marked as disposable.
C++11 introduced move constructors for this exact purpose:
ClassA::ClassA(ClassA&& ra)
: _ptr(ra._ptr)
{
ra._ptr = nullptr;
}
Alternatively you can declare _ptr to be a shared pointer:
std::shared_ptr<char[]> _ptr;
and then default denerated copy constructor will do just fine.
You should not copy the pointer, you should copy the context that the pointer is pointing to. You should also initialize the class by telling it how many elements you want, instead of allocating it by accessing a public pointer.
Since you want to copy the object, not move it, you should allocate resources in the new object when copying.
class A {
int* p_;
int size_;
public:
A(int size)
: p_(new int[size]()),
size_(size) {
}
A(const A &a)
: p_(new int[a.size_]),
size_(a.size_) {
std::copy(a.p_, a.p_ + a.size_, p_);
}
...
};
int main () {
A a(10);
vec.push_back(a);
}
However, if you know that the object you will copy isn't used after it's copied, you could move it's resources instead.
The problem with your implementation is that you will not be able to pass temporary objects as arguments for this copy-ctor (temporaries are always const). Like already mentioned the best solution would be to move to c++11 and use move semantics. If it is not possible shared_array can be an alternative.
Additional comment:
Avoid these kind of problems creating the object with new and storing pointers to the object in the vector.

Is copy constructor used for object initialization? How does it works and what is the difference B/W deep copy and shallow copy?

Is copy constructor used for object initialization? How does it works and what is the difference B/W deep copy and shallow copy?
The copy constructor is used to initilize the new object with the previously created object of the same class. By default compiler wrote a shallow copy. Shallow copy works fine when dynamic memory allocation is not involved because when dynamic memory allocation is involved then both objects will points towards the same memory location in a heap, Therefore to remove this problem we wrote deep copy so both objects have their own copy of attributes in a memory.
In order to read the details with complete examples and explanations you could see the article Constructors in C++.
shadow copy : the new object points to the same memory location pointed by the old object, which means that any change of the value of one of the both objects will affect the other one. particulary if you dispose one of the both object, the other will be dispose too.
deep copy : a memory is allocate to the new object and the value in this memory is equals to the value situated at the old object memory location. suitable for objects which have members like table or vector
if you don't write a copy constructor for a class, compiler will write one for you which usually do shadow copy. to write a copy constructor you write like usual constructor but the parameter is a reference to an object of the same class
class B //With copy constructor
{
private:
char *name;
public:
B()
{
name = new char[20];
}
~B()
{
delete name[];
}
//Copy constructor
B(const B &b)
{
name = new char[20];
strcpy(name, b.name);
}
};