class pointerDataClass
{
public:
void print() const;
//Function to output the value of x and
//the value of the array p
void setData();
//Function to input data into x and
//into the array p
void destroyP();
//Function to deallocate the memory space
//occupied by the array p
pointerDataClass(int sizeP = 10);
//constructor
//Creates an array of the size specified by the
//parameter sizeP; the default array size is 10
~pointerDataClass();
//destructor
//Deallocates the memory space occupied by the array p
pointerDataClass (const pointerDataClass& otherObject);
//copy constructor
private:
int x;
int lenP;
int *p; //pointer to an int array
};
The exercise was or is to write the main driver program to test the copy constructor lastchance.
So it definetly does not come from the text book.
It is written by me.
Mmm, apologies. @Keskiverto is right. Should be pointerDataClass list2 = list1;
to copy on construction rather than list2 = list1;
(with earlier declaration of list2).
Seemingly got away with it in C++ shell in this instance.
Your main driver program works fine lastchance but I was under the impression that pointers should be used because the chapter3 is dealing with pointers. I would appreciate if you could write it using pointers
Actually, it doesn't (or probably wouldn't if you tried to do much more with list1 and list2). See @Keskiverto's post for the proper information.
I suspect that the usage of pointers is confined to how they are used to access unnamed memory on the heap (where you are using "new" and "delete") rather than in your main program.
I'll try to rewrite main() with pointersEDIT. Scrub that, with the existing constructors that is asking for trouble!
#include <cassert>
#include <iostream>
class PointerDataClass {
public:
explicit PointerDataClass(int len_p_arg = 10);
PointerDataClass(const PointerDataClass& other);
PointerDataClass& operator=(const PointerDataClass& other);
PointerDataClass(PointerDataClass&& other);
PointerDataClass& operator=(PointerDataClass&& other);
void print() const;
void destroyP();
void setData();
~PointerDataClass();
private:
int x;
int len_p;
int* p;
};
PointerDataClass::PointerDataClass(int len_p_arg)
{
x = 0;
len_p = len_p_arg;
if(len_p_arg <= 0)
{
std::cout << "Array size must be positive.\n""Creating an array of size 10.\n";
len_p = 10;
}
p = newint[len_p] {};
assert(p != nullptr);
}
// Copy constructor:
PointerDataClass::PointerDataClass(const PointerDataClass& other)
{
x = other.x;
len_p = other.len_p;
p = newint[len_p];
assert(p != nullptr);
for(int i = 0; i < len_p; i++) {
p[i] = other.p[i];
}
}
// Copy assignment operator:
// (not copy&swap idiom)
PointerDataClass& PointerDataClass::operator=(const PointerDataClass& other)
{
if(this == &other) { return *this; }
x = other.x;
len_p = other.len_p;
p = newint[len_p];
assert(p != nullptr);
for(int i = 0; i < len_p; i++) {
p[i] = other.p[i];
}
return *this;
}
// Move constructor:
PointerDataClass::PointerDataClass(PointerDataClass&& other)
{
x = other.x;
other.x = 0;
len_p = other.len_p;
other.len_p = 0;
p = other.p;
other.p = nullptr;
}
// Move assignment operator:
PointerDataClass& PointerDataClass::operator=(PointerDataClass&& other)
{
if(this == &other) { return *this; }
delete [] p;
x = other.x;
other.x = 0;
len_p = other.len_p;
other.len_p = 0;
p = other.p;
other.p = nullptr;
return *this;
}
PointerDataClass::~PointerDataClass()
{
delete [] p;
}
void PointerDataClass::print() const
{
std::cout << "x = " << x
<< "; p = ";
for(int i = 0; i < len_p; ++i) {
std::cout << p[i] << ' ';
}
std::cout << '\n';
}
void PointerDataClass::setData()
{
std::cout << "Enter an integer for x: ";
std::cin >> x;
std::cout << "Enter " << len_p << " numbers: ";
for(int i = 0; i < len_p; ++i) {
std::cin >> p[i];
}
}
void PointerDataClass::destroyP()
{
delete [] p;
p = nullptr;
len_p = 0;
}
int main()
{
PointerDataClass* list1;
// Now list1 is pointing to an unknown memory area.
// It means that area could be read only or reserved or... whatever.
// You should not do anything with a pointer until you have made it
// point to a memory area you own!
list1 = new PointerDataClass();
// Now list1 is pointing to a valid memory area.
// You can operate on that memory area:
list1->setData();
// Since there's an assignment in it, the following line is to be read
// from right to left (the operations on the right of the assignments
// are executed before the once on the left):
// 1) A memory area is allocated for you;
// 2) the content of that memory area is copied from the memory area
// pointed to by list1 (thanks to the overloaded copy constructor);
// 3) a new pointer named list2 is created;
// 4) list2 is assigned the address of the newly created memory area:
PointerDataClass* list2 = new PointerDataClass(*list1);
std::cout << "list1 = " ;
list1->print() ;
std::cout << "\nlist2 = ";
list2->print();
std::cout << '\n';
delete list2; // release the allocated memory
// (Note: the destructor can't be protected)
list2 = nullptr; // make sure the pointer doesn't point any more
// to the previous (now deallocated) memory area
delete list1;
list1 = nullptr;
return 0;
}
Output:
Enter an integer for x: 666
Enter 10 numbers: 9 8 7 6 5 4 3 2 1 0
list1 = x = 666; p = 9 8 7 6 5 4 3 2 1 0
list2 = x = 666; p = 9 8 7 6 5 4 3 2 1 0
I know that the book won't teach it, but users of C++ should know the smart pointers:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
int main()
{
// lets not create uninitialized pointers. Ever.
// lets not use raw pointers
auto list1 = std::make_unique<PointerDataClass>();
list1->setData();
auto list2 = std::make_unique<PointerDataClass>( *list1 );
std::cout << "list1 = " ;
list1->print() ;
std::cout << "\nlist2 = ";
list2->print();
std::cout << '\n';
// the std::unique_ptr handles the deallocations
return 0;
}
The example class is very limited. It does not support demonstrating that the copy constructed object truly is a distinct deep copy and not a shallow copy that leads to double deletes.