I am learning dynamic memory allocation. I have the following class where 'class A' should own a dynamically allocated array in the constructor. Also the copy constructor and destructor should be modified. This is what I have so far...
#include <iostream>
#ifndef A_HH
#define A_HH
#include "B.hh"
class A {
public:
A() { B *array = new B[12];}
A(const A&) { /* Do not know what to put here..*/ }
~A() { delete[] array;}
private:
//B array[12] ; <- This is the array that I have to modify so it becomes dynamic.
B *array;
} ;
#endif
For starters your default constructor there is overriding the member variable "array" with a local variable of the same type, so you want the default constructor to look like this:
A() { array = new B[12]; }
Then the copy constructor presumably needs to deep copy the array over, but with a simple array you can't tell the arraysize at runtime. You need to either move to a smarter container (e.g. stl::vector) or store the size, but a naive copy constructor would look like this:
A(const A& other)
{
array = new B[12];
for(int i=0;i<12;i++)
{
array[i] = other.array[i];
}
}
Check out this code:
#include <iostream>
using namespace std;
class MyArray{
public:
int* array;
int length;
MyArray(int length){ // constructor which takes length of array as argument
this->length = length;
this->array = new int[this->length];
for(int i=0; i<this->length; i++){
this->array[i] = i;
}
}
MyArray(const MyArray &obj){
this->length = obj.length;
this->array = new int[this->length];
for(int i=0; i<this->length; i++)
{
this->array[i] = obj.array[i];
}
}
~MyArray(){ // destructor
delete[] this->array;
}
void print(){ // test method for printing the array
for(int i=0; i<this->length; i++){
cout << this->array[i] << endl;
}
cout << endl;
}
private:
protected:
};
int main()
{
MyArray *array = new MyArray(10);
MyArray *array2 = new MyArray(*array); // call copy constructor
array->print();
array2->print();
delete array;
delete array2;
}
Related
I have overloaded 'new' operator as a member function for my class Array. I need help overloading it as a friend function. See the program below:
#include<iostream>
using namespace std;
class Array {
private:
int *arr;
int size;
public:
void * operator new (size_t size)
{
void *ptr = ::new Array;
return ptr;
}
void operator delete(void *ptr)
{
::delete ptr;
}
Array(int n=5)
{
this->size = n;
this->arr = new int[n];
}
void input()
{
cout<<"Enter the values"<<endl;
for(int i=0; i<size; i++)
cin>>arr[i];
}
void show()
{
for(int i=0; i<size; i++)
cout<<arr[i]<<" ";
cout<<endl;
}
};
int main()
{
Array *A = new Array(4);
A->input();
A->show();
return 0;
}
What I tried to do in friend function:
void * operator new (size_t size) throw (std::bad_alloc)
{
void * ptr = ::new Array;
return ptr;
}
I got an infinite loop for this. Can anyone help me here?
Edit : Grammar
There can be only one ::operator new(size_t). Normally the standard library provides one. If you provide one, it replaces (doesn't overload) the one provided by the standard library.
Your version calls itself unconditionally (there's no other ::operator new(size_t)) so there's an unbounded recursion and a stack overflow in there.
You cannot provide ::operator new(size_t) and hope it will work together with the system-provided ::operator new(size_t) but only for your class.
The only way to make a global overloaded operator new is to give it a different signature, e.g.
enum foo {bar};
void* operator new (std::size_t size, foo) { ... }
...
Array* arr = new (bar) Array;
But you can use it to allocate any type, not just Array, regardless of which classes decide to befriend it.
So just adding on above answer you can overload your operator new and delete in following manner and this will work because one inside constructor will call operator new[] not operator new.Also no need to make this friend since you are not accessing any private data member in this function:
#include <iostream>
#include <string>
using namespace std;
class Array {
private:
int *arr;
int size;
public:
Array(int n=5)
{
this->size = n;
this->arr = new int[n];
}
void input()
{
cout<<"Enter the values"<<endl;
for(int i=0; i<size; i++)
cin>>arr[i];
}
void show()
{
for(int i=0; i<size; i++)
cout<<arr[i]<<" ";
cout<<endl;
}
};
void * operator new (size_t size)
{
void *ptr = std::malloc(size);
return ptr;
}
void operator delete(void *ptr)
{
std::free(ptr);
}
int main()
{
Array *A = new Array(4);
A->input();
A->show();
return 0;
}
So I have this code, and when I run it, I got a run time error when class B is trying to call its destructor. The destructor of class A seems fine. I wonder what's wrong with this code. Thanks for helping.
#include <iostream>
using namespace std;
class A{
public:
//Constructor
A(int N){
this->N = N;
array = new int[N];
}
//Copy Constructor
A(const A& A1){
this->N = A1.N;
//Create new array with exact size
this->array = new int[N];
//Copy element
for(int i=0; i<N; i++){
this->array[i]= A1.array[i];
}
}
~A(){
delete [] array;
cout<<"Success"<<endl;
}
int N;
int* array;
};
class B{
public:
B(const A& array1){
array = new A(array1);
}
~B(){
delete [] array;
}
A* array;
};
using namespace std;
int main(){
A matrix1(10);
B testing(matrix1);
return 0;
}
In B::~B(), you call delete[] on B::array after allocating it via new in B::B(const A&).
This is illegal: You must always pair new with delete and new[] with delete[].
you can't use the delete [] when you don't create an array of elements, your destructor must be like:
~B(){
delete array;
}
Remove the [] when you delete the allocated memory in b because you allocated for just one element and the [] makes the compiler assumes that you are deleting an array allocated memory.
I have a question regarding how the destructor is called. For example, I created the following foo class and supplied with copy constructor, destructor and overloaded the assignment operator. I created a dynamic array of this foo objects and used the operator "=" to assign individual element of the array. I am very confused, immediately after the assignment operation, the destructor is called and when I want to access the data in the newly assigned object, I got very confusing result.Any suggestions?
#include <iostream>
using namespace std;
bool debug = true;
class foo{
private:
int n;
void init(int _n);
public:
int* arr; // just to make it accessible so that we can tract the contents;
foo(int _n);
foo(int* _a, int len);
foo(const foo & rhs);
foo & operator=(const foo & rhs);
~foo();
};
void foo::init(int _n = 0){
n = _n;
arr = new int[n];
for(int i = 0; i != n; i++) arr[i] = 0;
}
foo::foo(int _n = 0){
init(_n);
}
foo::foo(int*_a, int len){
init(len);
for(int i = 0; i< len; i++) arr[i] = _a[i];
}
foo::foo(const foo &rhs){
operator = (rhs);
}
foo& foo::operator= (const foo &rhs){
if(debug) cout<<"\nassignment operator overloaded";
if (this != &rhs){
if(n != 0) {
n = rhs.n;
delete [] arr;
arr = new int[n];
for(int i = 0; i < n; i++) arr[i] = rhs.arr[i];
}
}
return *this;
}
foo::~foo(){
if (debug)cout << "\ndestructor called\n";
delete []arr;
}
int main(){
{ // a explicit block to see when the destructor is called;
foo* f = new foo[4];
int n = 4;
int a[] = {0,1,2,3};
for(int i = 0; i < n;i++) {
cout<<i;
f[i] = foo(a, i);
cout<<f[i].arr[i]<<"\n"; // result is some seemingly random number;
}
}
system("PAUSE");
}*
When you do this:
f[i] = foo(a, i);
a temporary foo object is created on the RHS of the assignment operator. It is then used to assign to the foo on the LHS of the operator. Then, it is destroyed, therefore its destructor is called.
The reason for the garbage values after the assignments is probably that n is 0 in all the foos in the array. Your assignment operator is broken. You may want to have a look at the copy and swap idiom.
A big no no! Delegating initialization of an uninitialized object to the assignment operator is a no good idea:
foo::foo(const foo &rhs){
operator = (rhs);
}
Better is:
foo::foo(const foo &rhs)
: n(rhs.n), arr(new int[n])
{
// copy rhs.arr to arr
}
// Note: Passing by value:
foo& operator = (foo rhs) {
std::swap(n, rhs.n);
std::swap(arr, rhs.arr);
return *this;
// Note: The swapped rhs will do the cleanup in the destructor
}
You will end up with less coding and exception safety
Another issue is:
cout << f[i].arr[i] << "\n"
You are printing an undefined 'end' value (arr[i] == arr[n])
I'm trying to implement a container that allocated memory to the heap, but it seems as though my base constructor and my argument constructor don't like each other. Below, I've posted the code without anything commented out. As it stands, it crashes.
#include <iostream>
using namespace std;
class foo
{
public:
foo() {size=1; vals = new double[1]; vals[0]=0;}
~foo() {delete[] vals;}
foo(const foo& other)
{
size=other.getsize();
delete[] vals;
vals = new double[size];
for(long unsigned i=0; i<size; i++)
vals[i]=other[i];
}
foo& operator=(const foo& other)
{
size=other.getsize();
delete[] vals;
vals = new double[size];
for(long unsigned i=0; i<size; i++)
vals[i]=other[i];
return *this;
}
foo(double* invals, long unsigned insize)
{
size=insize;
delete[] vals;
vals = new double[size];
for(long unsigned i=0; i<size; i++)
vals[i]=invals[i];
}
double operator[](long unsigned i) const {return vals[i];}
long unsigned getsize() const {return size;}
private:
double* vals;
long unsigned size;
};
int main()
{
double bar[3] = {5,2,8};
foo B(bar, 3);
cout<< B[0]<< " "<< B[1]<< " "<< B[2]<<endl; //couts fine
foo A; //crashes here
return 0;
}
However, when I change main to be:
int main()
{
double bar[3] = {5,2,8};
foo B(bar, 3);
cout<< B[0]<< " "<< B[1]<< " "<< B[2]<<endl; //couts fine
foo A(); //works now
return 0;
}
It runs fine. But then I can't assign A = B because it thinks foo is a function or something.
I assume you have some really compelling reason not to use std::vector<double> here...
But anyway... in your copy constructor, you don't want to delete[] vals.
foo(const foo& other)
{
size=other.getsize();
vals = new double[size];
for(long unsigned i=0; i<size; i++)
vals[i]=other[i];
}
When the copy constructor is called, your object hasn't been initialized yet, so vals* doesn't even point to anything valid. Therefore, deleting it invokes undefined behavior (and your program crashes.) You only need to delete[] vals in your assignment operator.
Also, when you declare the Foo variable A, you don't want those parentheses after the variable name. Just say:
foo A;
When you place those parenthesis after the variable name, you're actually writing a function declaration using syntax inherited from C, and A becomes a function pointer type.
I have a following class foo
class foo
{
int *arr; // arr holds numbers
int sz; // size of array
public:
// Suppose I have made default and 1 parameter c'tor
foo(const foo &f)
{
sz = f.sz;
arr = new int[sz];
for(int i=0;i<sz;i++)
arr[i]=f.arr[i];
}
};
int main()
{
foo x(5); //5 is size of array
const foo y = x; //doesn't work as I haven't initialized in member-initialization list, but how to write for loop in member initialization list ?
}
So How do I write for loop in member initialization list ?
You could just use a std::vector in this caseā¦ anyways.
Typically, I will create a private static method which will perform the allocation and copy. Then the initialization list may be used:
static int* CloneInts(const foo& f) {
int* ints = new ...
...copy them from #a f.arr...
return ints;
}
Then your init-list would look like:
foo(const foo& f) : arr(CloneInts(f)), sz(f.sz) {
Have you tried constructing it with the copy constructor directly?
const foo y(x);
You should clarify your problem, because the one in the question doesn't actually exist.
The const foo y = x; line will compile and work with that copy constructor. A const object under construction isn't "const' until the constructor has completed. So the constructor body is permitted to modify the object even if the object being constructed is const.
Also note that the loop in the example isn't even modifying anything that's ever const - since the array is allocated dynamically, those array elements are modifiable even if the object itself isn't. For example, the arr pointer isn't modifiable after the ctor has completed, but arr[0] still is.
Try out the following to see both points in action:
#include <stdio.h>
#include <algorithm>
class foo
{
int *arr; // arr holds numbers
int sz; // size of array
public:
foo() : arr(0), sz(0) { puts("default ctor");}
foo(int x) : arr(0), sz(x) {
puts( "int ctor");
arr = new int[sz];
for(int i=0;i<sz;i++)
arr[i]=0;
}
foo(const foo &f)
{
puts("copy ctor");
sz = f.sz;
arr = new int[sz];
for(int i=0;i<sz;i++)
arr[i]=f.arr[i];
}
~foo() {
delete [] arr;
}
foo& operator=(const foo& rhs) {
if (this != &rhs) {
foo tmp(rhs);
std::swap( arr, tmp.arr);
std::swap( sz, tmp.sz);
}
return *this;
}
void update() const {
for(int i = 0; i < sz; i++) {
arr[i] = arr[i] + 1;
}
}
void dump() const {
for(int i = 0; i < sz; i++) {
printf("%d ", arr[i]);
}
puts("");
}
};
int main()
{
foo x(5); //5 is size of array
const foo y = x;
y.dump();
y.update(); // can still modify the int array, even though `y` is const
y.dump();
}
I think you may be confusing constructing const objects with constructing objects that have const members since those members must be initialized in the initialization list.